/*
	FIXME:
	1. glGetFloatv returns more than one float for 
	2. glGetIntegerv returns more than one integer for 
	3. glGetLightfv returns morethan one float
	4. glGetBooleanv returns more than one bool for
	5. glGetTexImage is dodgy & probably wrong
	6  glGetTexLevelParameterfv incomplete

	IFFY:
	glFeedBackBuffer
*/

#include <caml/mlvalues.h>
#include <caml/alloc.h>
#include <caml/memory.h>
#include <caml/fail.h>
#include <caml/callback.h>
#include <caml/custom.h>
#include <caml/intext.h>
#include <caml/bigarray.h>

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#ifdef _WIN32
	#include <windows.h>
	#define dlopen(lib, flag) LoadLibrary(lib)
	#define dlsym GetProcAddress
	#define LIBGL   "opengl32.dll"
	#define LIBSDL  "SDL.dll"
#endif

#ifdef __unix__
	#include <dlfcn.h>
	#ifndef APIENTRY
		#define APIENTRY
	#endif
	#ifndef HMODULE
		#define HMODULE void*
	#endif
	#define LIBGL   "libGL.so"
	#define LIBSDL  "libSDL.so"
#endif

#if defined(__APPLE__) && defined(__GNUC__)
	#include <dlfcn.h>
	#ifndef APIENTRY
		#define APIENTRY
	#endif
	#ifndef HMODULE
		#define HMODULE void*
	#endif
	#define LIBGL   "libGL.dylib"
	#define LIBSDL  "libSDL.dylib"
#endif

static HMODULE libSDL=NULL;

#define DECLARE_FUNCTION(func, args, ret)						\
typedef ret APIENTRY ( *pstub_##func)args;						\
static pstub_##func stub_##func = NULL;							\
static int loaded_##func = 0;

#define LOAD_FUNCTION(lib, func) 								\
	if(!loaded_##func)											\
	{															\
		init_lib ();											\
		stub_##func = (pstub_##func)dlsym(lib, #func);			\
		if(stub_##func)											\
			loaded_##func = 1;									\
		else													\
			caml_failwith("Unable to load " #func);				\
	}

#define FN(func) ( *stub_##func)

#define LOAD_GL_FUNCTION(func)									\
	if(!loaded_##func)											\
	{															\
		stub_##func = 											\
			(pstub_##func)FN(SDL_GL_GetProcAddress)( #func);	\
		if(stub_##func)											\
			loaded_##func = 1;									\
		else													\
			caml_failwith("Unable to load " #func);				\
	}
	
#define MIN(a,b) ((a) < (b) ? (a) : (b))

static void init_lib()
{
	if(libSDL)return;
	libSDL = dlopen(LIBSDL,RTLD_LAZY);
	if(libSDL == NULL) caml_failwith("Unable to load " LIBSDL);
}

#define GL_VERSION 		0x00001f02
#define GL_DOUBLE 		0x0000140a
#define GL_INT 			0x00001405
#define GL_UNSIGNED_INT 0x00001404


/************************* SDL definitions ************************************/

#define	SDL_INIT_TIMER		0x00000001
#define SDL_INIT_AUDIO		0x00000010
#define SDL_INIT_VIDEO		0x00000020
#define SDL_INIT_CDROM		0x00000100
#define SDL_INIT_JOYSTICK	0x00000200
#define SDL_INIT_NOPARACHUTE	0x00100000	
#define SDL_INIT_EVENTTHREAD	0x01000000	
#define SDL_INIT_EVERYTHING	0x0000FFFF

#define SDL_SWSURFACE	0x00000000	
#define SDL_HWSURFACE	0x00000001	
#define SDL_ASYNCBLIT	0x00000004	
#define SDL_ANYFORMAT	0x10000000	
#define SDL_HWPALETTE	0x20000000	
#define SDL_DOUBLEBUF	0x40000000	
#define SDL_FULLSCREEN	0x80000000	
#define SDL_OPENGL      0x00000002     
#define SDL_OPENGLBLIT	0x0000000A	
#define SDL_RESIZABLE	0x00000010	
#define SDL_NOFRAME	    0x00000020	
#define SDL_HWACCEL	    0x00000100	
#define SDL_SRCCOLORKEY	0x00001000	
#define SDL_RLEACCELOK	0x00002000	
#define SDL_RLEACCEL	0x00004000	
#define SDL_SRCALPHA	0x00010000	
#define SDL_PREALLOC	0x01000000	

#define AUDIO_U8	0x0008
#define AUDIO_S8	0x8008
#define AUDIO_U16LSB	0x0010
#define AUDIO_S16LSB	0x8010
#define AUDIO_U16MSB	0x1010
#define AUDIO_S16MSB	0x9010
#define AUDIO_U16	AUDIO_U16LSB
#define AUDIO_S16	AUDIO_S16LSB

#define SDL_MUSTLOCK(surface)	\
    (surface->offset ||		    \
    ((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0))

#define SDL_APPMOUSEFOCUS	0x01		
#define SDL_APPINPUTFOCUS	0x02		
#define SDL_APPACTIVE		0x04		

#define SDL_LoadBMP(file)	\
    FN(SDL_LoadBMP_RW)(FN(SDL_RWFromFile)(file, "rb"), 1)

#define SDL_SaveBMP(surface, file) \
	FN(SDL_SaveBMP_RW)(surface, FN(SDL_RWFromFile)(file, "wb"), 1)

#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
	FN(SDL_LoadWAV_RW)(FN(SDL_RWFromFile)(file,"rb"),1,spec,audio_buf,audio_len)

typedef int8_t		Sint8;
typedef uint8_t		Uint8;
typedef int16_t		Sint16;
typedef uint16_t	Uint16;
typedef int32_t		Sint32;
typedef uint32_t	Uint32;

typedef enum SDL_bool {
	SDL_FALSE = 0,
	SDL_TRUE  = 1
} SDL_bool;

typedef struct SDL_AudioSpec {
	int freq;		
	Uint16 format;		
	Uint8  channels;	
	Uint8  silence;		
	Uint16 samples;		
	Uint16 padding;		
	Uint32 size;		
	void ( *fncallback)(void* userdata, Uint8* stream, int len);
	void*  userdata;
} SDL_AudioSpec;

typedef struct SDL_AudioCVT {
	int needed;			
	Uint16 src_format;		
	Uint16 dst_format;		
	double rate_incr;		
	Uint8* buf;			
	int    len;			
	int    len_cvt;			
	int    len_mult;		
	double len_ratio; 	
	void ( *filters[10])(struct SDL_AudioCVT* cvt, Uint16 format);
	int filter_index;		
} SDL_AudioCVT;

typedef enum {
	SDL_AUDIO_STOPPED = 0,
	SDL_AUDIO_PLAYING,
	SDL_AUDIO_PAUSED
} SDL_audiostatus;

typedef struct SDL_Rect {
	Sint16 x, y;
	Uint16 w, h;
} SDL_Rect;

typedef struct SDL_Color {
	Uint8 r;
	Uint8 g;
	Uint8 b;
	Uint8 unused;
} SDL_Color;

typedef struct SDL_Palette {
	int       ncolors;
	SDL_Color* colors;
} SDL_Palette;

typedef struct SDL_PixelFormat {
	SDL_Palette* palette;
	Uint8  BitsPerPixel;
	Uint8  BytesPerPixel;
	Uint8  Rloss;
	Uint8  Gloss;
	Uint8  Bloss;
	Uint8  Aloss;
	Uint8  Rshift;
	Uint8  Gshift;
	Uint8  Bshift;
	Uint8  Ashift;
	Uint32 Rmask;
	Uint32 Gmask;
	Uint32 Bmask;
	Uint32 Amask;
	Uint32 colorkey;
	Uint8  alpha;
} SDL_PixelFormat;

typedef struct SDL_Surface {
	Uint32 flags;				
	SDL_PixelFormat* format;		
	int w, h;				
	Uint16 pitch;				
	void* pixels;				
	int offset;				
	struct private_hwdata* hwdata;
	SDL_Rect clip_rect;			
	Uint32 unused1;				
	Uint32 locked;				
	struct SDL_BlitMap* map;		
	unsigned int format_version;		
	int refcount;				
} SDL_Surface;

typedef enum {
    SDL_GL_RED_SIZE,
    SDL_GL_GREEN_SIZE,
    SDL_GL_BLUE_SIZE,
    SDL_GL_ALPHA_SIZE,
    SDL_GL_BUFFER_SIZE,
    SDL_GL_DOUBLEBUFFER,
    SDL_GL_DEPTH_SIZE,
    SDL_GL_STENCIL_SIZE,
    SDL_GL_ACCUM_RED_SIZE,
    SDL_GL_ACCUM_GREEN_SIZE,
    SDL_GL_ACCUM_BLUE_SIZE,
    SDL_GL_ACCUM_ALPHA_SIZE,
    SDL_GL_STEREO,
    SDL_GL_MULTISAMPLEBUFFERS,
    SDL_GL_MULTISAMPLESAMPLES,
    SDL_GL_ACCELERATED_VISUAL,
    SDL_GL_SWAP_CONTROL
} SDL_GLattr;

typedef enum {
    SDL_NOEVENT = 0,			
    SDL_ACTIVEEVENT,			
    SDL_KEYDOWN,			
    SDL_KEYUP,			
    SDL_MOUSEMOTION,			
    SDL_MOUSEBUTTONDOWN,		
    SDL_MOUSEBUTTONUP,		
    SDL_JOYAXISMOTION,		
    SDL_JOYBALLMOTION,		
    SDL_JOYHATMOTION,		
    SDL_JOYBUTTONDOWN,		
    SDL_JOYBUTTONUP,			
    SDL_QUIT,			
    SDL_SYSWMEVENT,			
    SDL_EVENT_RESERVEDA,		
    SDL_EVENT_RESERVEDB,		
    SDL_VIDEORESIZE,			
    SDL_VIDEOEXPOSE,			
    SDL_EVENT_RESERVED2,		
    SDL_EVENT_RESERVED3,		
    SDL_EVENT_RESERVED4,		
    SDL_EVENT_RESERVED5,		
    SDL_EVENT_RESERVED6,		
    SDL_EVENT_RESERVED7,		
    SDL_USEREVENT = 24,
    SDL_NUMEVENTS = 32
} SDL_EventType;

typedef struct SDL_ActiveEvent {
	Uint8 type;	
	Uint8 gain;	
	Uint8 state;	
} SDL_ActiveEvent;

typedef struct SDL_keysym {
	Uint8 scancode;			
	int sym;			
	int mod;			
	Uint16 unicode;			
} SDL_keysym;

typedef struct SDL_KeyboardEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 state;	
	SDL_keysym keysym;
} SDL_KeyboardEvent;

typedef struct SDL_MouseMotionEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 state;	
	Uint16 x, y;	
	Sint16 xrel;	
	Sint16 yrel;	
} SDL_MouseMotionEvent;

typedef struct SDL_MouseButtonEvent {
	Uint8 type;
	Uint8 which;	
	Uint8 button;	
	Uint8 state;	
	Uint16 x, y;	
} SDL_MouseButtonEvent;

typedef struct SDL_JoyAxisEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 axis;	
	Sint16 value;	
} SDL_JoyAxisEvent;

typedef struct SDL_JoyBallEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 ball;	
	Sint16 xrel;	
	Sint16 yrel;	
} SDL_JoyBallEvent;

typedef struct SDL_JoyHatEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 hat;	
	Uint8 value;	
} SDL_JoyHatEvent;

typedef struct SDL_JoyButtonEvent {
	Uint8 type;	
	Uint8 which;	
	Uint8 button;	
	Uint8 state;	
} SDL_JoyButtonEvent;

typedef struct SDL_ResizeEvent {
	Uint8 type;	
	int w;		
	int h;		
} SDL_ResizeEvent;

typedef struct SDL_ExposeEvent {
	Uint8 type;	
} SDL_ExposeEvent;

typedef struct SDL_QuitEvent {
	Uint8 type;	
} SDL_QuitEvent;

typedef struct SDL_UserEvent {
	Uint8 type;	
	int code;	
	void* data1;	
	void* data2;	
} SDL_UserEvent;

struct SDL_SysWMmsg;
typedef struct SDL_SysWMmsg SDL_SysWMmsg;
typedef struct SDL_SysWMEvent {
	Uint8 type;
	SDL_SysWMmsg* msg;
} SDL_SysWMEvent;

typedef union SDL_Event {
	Uint8 type;
	SDL_ActiveEvent active;
	SDL_KeyboardEvent key;
	SDL_MouseMotionEvent motion;
	SDL_MouseButtonEvent button;
	SDL_JoyAxisEvent jaxis;
	SDL_JoyBallEvent jball;
	SDL_JoyHatEvent jhat;
	SDL_JoyButtonEvent jbutton;
	SDL_ResizeEvent resize;
	SDL_ExposeEvent expose;
	SDL_QuitEvent quit;
	SDL_UserEvent user;
	SDL_SysWMEvent syswm;
} SDL_Event;

typedef enum {
	SDL_GRAB_QUERY = -1,
	SDL_GRAB_OFF = 0,
	SDL_GRAB_ON = 1,
	SDL_GRAB_FULLSCREEN	
} SDL_GrabMode;

typedef struct SDL_RWops {
	int ( *seek)(struct SDL_RWops* context, int offset, int whence);
	int ( *read)(struct SDL_RWops* context, void* ptr, int size, int maxnum);
	int ( *write)(struct SDL_RWops* context, const void* ptr, int size, int num);
	int ( *close)(struct SDL_RWops* context);
	Uint32 type;
	union {
#if defined(__WIN32__) && !defined(__SYMBIAN32__)
	    struct {
		int   append;
		void* h;
		struct {
		    void* data;
		    int size;
		    int left;
		} buffer;
	    } win32io;
#endif
	    struct {
		int autoclose;
	 	FILE* fp;
	    } stdio;
	    struct {
		Uint8* base;
	 	Uint8* here;
		Uint8* stop;
	    } mem;
	    struct {
		void* data1;
	    } unknown;
	} hidden;
} SDL_RWops;

typedef enum {
	SDLK_UNKNOWN	= 0,
	SDLK_FIRST		= 0,
	SDLK_BACKSPACE	= 8,
	SDLK_TAB		= 9,
	SDLK_CLEAR		= 12,
	SDLK_RETURN		= 13,
	SDLK_PAUSE		= 19,
	SDLK_ESCAPE		= 27,
	SDLK_SPACE		= 32,
	SDLK_EXCLAIM	= 33,
	SDLK_QUOTEDBL	= 34,
	SDLK_HASH		= 35,
	SDLK_DOLLAR		= 36,
	SDLK_AMPERSAND	= 38,
	SDLK_QUOTE		= 39,
	SDLK_LEFTPAREN	= 40,
	SDLK_RIGHTPAREN	= 41,
	SDLK_ASTERISK	= 42,
	SDLK_PLUS		= 43,
	SDLK_COMMA		= 44,
	SDLK_MINUS		= 45,
	SDLK_PERIOD		= 46,
	SDLK_SLASH		= 47,
	SDLK_0			= 48,
	SDLK_1			= 49,
	SDLK_2			= 50,
	SDLK_3			= 51,
	SDLK_4			= 52,
	SDLK_5			= 53,
	SDLK_6			= 54,
	SDLK_7			= 55,
	SDLK_8			= 56,
	SDLK_9			= 57,
	SDLK_COLON		= 58,
	SDLK_SEMICOLON	= 59,
	SDLK_LESS		= 60,
	SDLK_EQUALS		= 61,
	SDLK_GREATER	= 62,
	SDLK_QUESTION	= 63,
	SDLK_AT			= 64,
	SDLK_LEFTBRACKET    = 91,
	SDLK_BACKSLASH	= 92,
	SDLK_RIGHTBRACKET	= 93,
	SDLK_CARET		= 94,
	SDLK_UNDERSCORE	= 95,
	SDLK_BACKQUOTE	= 96,
	SDLK_a			= 97,
	SDLK_b			= 98,
	SDLK_c			= 99,
	SDLK_d			= 100,
	SDLK_e			= 101,
	SDLK_f			= 102,
	SDLK_g			= 103,
	SDLK_h			= 104,
	SDLK_i			= 105,
	SDLK_j			= 106,
	SDLK_k			= 107,
	SDLK_l			= 108,
	SDLK_m			= 109,
	SDLK_n			= 110,
	SDLK_o			= 111,
	SDLK_p			= 112,
	SDLK_q			= 113,
	SDLK_r			= 114,
	SDLK_s			= 115,
	SDLK_t			= 116,
	SDLK_u			= 117,
	SDLK_v			= 118,
	SDLK_w			= 119,
	SDLK_x			= 120,
	SDLK_y			= 121,
	SDLK_z			= 122,
	SDLK_DELETE		= 127,
	SDLK_WORLD_0	= 160,		
	SDLK_WORLD_1	= 161,
	SDLK_WORLD_2	= 162,
	SDLK_WORLD_3	= 163,
	SDLK_WORLD_4	= 164,
	SDLK_WORLD_5	= 165,
	SDLK_WORLD_6	= 166,
	SDLK_WORLD_7	= 167,
	SDLK_WORLD_8	= 168,
	SDLK_WORLD_9	= 169,
	SDLK_WORLD_10	= 170,
	SDLK_WORLD_11	= 171,
	SDLK_WORLD_12	= 172,
	SDLK_WORLD_13	= 173,
	SDLK_WORLD_14	= 174,
	SDLK_WORLD_15	= 175,
	SDLK_WORLD_16	= 176,
	SDLK_WORLD_17	= 177,
	SDLK_WORLD_18	= 178,
	SDLK_WORLD_19	= 179,
	SDLK_WORLD_20	= 180,
	SDLK_WORLD_21	= 181,
	SDLK_WORLD_22	= 182,
	SDLK_WORLD_23	= 183,
	SDLK_WORLD_24	= 184,
	SDLK_WORLD_25	= 185,
	SDLK_WORLD_26	= 186,
	SDLK_WORLD_27	= 187,
	SDLK_WORLD_28	= 188,
	SDLK_WORLD_29	= 189,
	SDLK_WORLD_30	= 190,
	SDLK_WORLD_31	= 191,
	SDLK_WORLD_32	= 192,
	SDLK_WORLD_33	= 193,
	SDLK_WORLD_34	= 194,
	SDLK_WORLD_35	= 195,
	SDLK_WORLD_36	= 196,
	SDLK_WORLD_37	= 197,
	SDLK_WORLD_38	= 198,
	SDLK_WORLD_39	= 199,
	SDLK_WORLD_40	= 200,
	SDLK_WORLD_41	= 201,
	SDLK_WORLD_42	= 202,
	SDLK_WORLD_43	= 203,
	SDLK_WORLD_44	= 204,
	SDLK_WORLD_45	= 205,
	SDLK_WORLD_46	= 206,
	SDLK_WORLD_47	= 207,
	SDLK_WORLD_48	= 208,
	SDLK_WORLD_49	= 209,
	SDLK_WORLD_50	= 210,
	SDLK_WORLD_51	= 211,
	SDLK_WORLD_52	= 212,
	SDLK_WORLD_53	= 213,
	SDLK_WORLD_54	= 214,
	SDLK_WORLD_55	= 215,
	SDLK_WORLD_56	= 216,
	SDLK_WORLD_57	= 217,
	SDLK_WORLD_58	= 218,
	SDLK_WORLD_59	= 219,
	SDLK_WORLD_60	= 220,
	SDLK_WORLD_61	= 221,
	SDLK_WORLD_62	= 222,
	SDLK_WORLD_63	= 223,
	SDLK_WORLD_64	= 224,
	SDLK_WORLD_65	= 225,
	SDLK_WORLD_66	= 226,
	SDLK_WORLD_67	= 227,
	SDLK_WORLD_68	= 228,
	SDLK_WORLD_69	= 229,
	SDLK_WORLD_70	= 230,
	SDLK_WORLD_71	= 231,
	SDLK_WORLD_72	= 232,
	SDLK_WORLD_73	= 233,
	SDLK_WORLD_74	= 234,
	SDLK_WORLD_75	= 235,
	SDLK_WORLD_76	= 236,
	SDLK_WORLD_77	= 237,
	SDLK_WORLD_78	= 238,
	SDLK_WORLD_79	= 239,
	SDLK_WORLD_80	= 240,
	SDLK_WORLD_81	= 241,
	SDLK_WORLD_82	= 242,
	SDLK_WORLD_83	= 243,
	SDLK_WORLD_84	= 244,
	SDLK_WORLD_85	= 245,
	SDLK_WORLD_86	= 246,
	SDLK_WORLD_87	= 247,
	SDLK_WORLD_88	= 248,
	SDLK_WORLD_89	= 249,
	SDLK_WORLD_90	= 250,
	SDLK_WORLD_91	= 251,
	SDLK_WORLD_92	= 252,
	SDLK_WORLD_93	= 253,
	SDLK_WORLD_94	= 254,
	SDLK_WORLD_95	= 255,		
	SDLK_KP0		= 256,
	SDLK_KP1		= 257,
	SDLK_KP2		= 258,
	SDLK_KP3		= 259,
	SDLK_KP4		= 260,
	SDLK_KP5		= 261,
	SDLK_KP6		= 262,
	SDLK_KP7		= 263,
	SDLK_KP8		= 264,
	SDLK_KP9		= 265,
	SDLK_KP_PERIOD	= 266,
	SDLK_KP_DIVIDE	= 267,
	SDLK_KP_MULTIPLY= 268,
	SDLK_KP_MINUS	= 269,
	SDLK_KP_PLUS	= 270,
	SDLK_KP_ENTER	= 271,
	SDLK_KP_EQUALS	= 272,
	SDLK_UP			= 273,
	SDLK_DOWN		= 274,
	SDLK_RIGHT		= 275,
	SDLK_LEFT		= 276,
	SDLK_INSERT		= 277,
	SDLK_HOME		= 278,
	SDLK_END		= 279,
	SDLK_PAGEUP		= 280,
	SDLK_PAGEDOWN	= 281,
	SDLK_F1			= 282,
	SDLK_F2			= 283,
	SDLK_F3			= 284,
	SDLK_F4			= 285,
	SDLK_F5			= 286,
	SDLK_F6			= 287,
	SDLK_F7			= 288,
	SDLK_F8			= 289,
	SDLK_F9			= 290,
	SDLK_F10		= 291,
	SDLK_F11		= 292,
	SDLK_F12		= 293,
	SDLK_F13		= 294,
	SDLK_F14		= 295,
	SDLK_F15		= 296,
	SDLK_NUMLOCK	= 300,
	SDLK_CAPSLOCK	= 301,
	SDLK_SCROLLOCK	= 302,
	SDLK_RSHIFT		= 303,
	SDLK_LSHIFT		= 304,
	SDLK_RCTRL		= 305,
	SDLK_LCTRL		= 306,
	SDLK_RALT		= 307,
	SDLK_LALT		= 308,
	SDLK_RMETA		= 309,
	SDLK_LMETA		= 310,
	SDLK_LSUPER		= 311,		
	SDLK_RSUPER		= 312,		
	SDLK_MODE		= 313,		
	SDLK_COMPOSE	= 314,		
	SDLK_HELP		= 315,
	SDLK_PRINT		= 316,
	SDLK_SYSREQ		= 317,
	SDLK_BREAK		= 318,
	SDLK_MENU		= 319,
	SDLK_POWER		= 320,	
	SDLK_EURO		= 321,	
	SDLK_UNDO		= 322,	
	SDLK_LAST
} SDLKey;

typedef enum {
  KMOD_NONE  = 0x0000,
  KMOD_LSHIFT= 0x0001,
  KMOD_RSHIFT= 0x0002,
  KMOD_LCTRL = 0x0040,
  KMOD_RCTRL = 0x0080,
  KMOD_LALT  = 0x0100,
  KMOD_RALT  = 0x0200,
  KMOD_LMETA = 0x0400,
  KMOD_RMETA = 0x0800,
  KMOD_NUM   = 0x1000,
  KMOD_CAPS  = 0x2000,
  KMOD_MODE  = 0x4000,
} SDLMod;

/* SDL functions */
DECLARE_FUNCTION(SDL_BuildAudioCVT, (SDL_AudioCVT*, Uint16, Uint8, int,	Uint16, Uint8, int), int);
DECLARE_FUNCTION(SDL_CloseAudio, (void), void);
DECLARE_FUNCTION(SDL_ConvertAudio, (SDL_AudioCVT* ), int);
DECLARE_FUNCTION(SDL_CreateRGBSurface, (Uint32, int, int, int, Uint32, Uint32, Uint32, Uint32), SDL_Surface* );
DECLARE_FUNCTION(SDL_Delay, (Uint32), void);
DECLARE_FUNCTION(SDL_DisplayFormat, (SDL_Surface* ), SDL_Surface* );
DECLARE_FUNCTION(SDL_EnableKeyRepeat, (int, int), int);
DECLARE_FUNCTION(SDL_EnableUNICODE, (int), int);
DECLARE_FUNCTION(SDL_EventState, (Uint8, int), Uint8);
DECLARE_FUNCTION(SDL_FillRect, (SDL_Surface*, SDL_Rect*, Uint32), int);
DECLARE_FUNCTION(SDL_Flip, (SDL_Surface* ), int);
DECLARE_FUNCTION(SDL_FreeSurface, (SDL_Surface* ), void);
DECLARE_FUNCTION(SDL_FreeWAV, (Uint8* ), void);
DECLARE_FUNCTION(SDL_GetAppState, (void), Uint8);
DECLARE_FUNCTION(SDL_GetAudioStatus, (void), SDL_audiostatus);
DECLARE_FUNCTION(SDL_GetError, (void), char* );
DECLARE_FUNCTION(SDL_GetKeyName, (int), char* );
DECLARE_FUNCTION(SDL_GetModState, (void), int);
DECLARE_FUNCTION(SDL_GetMouseState, (int*, int* ), Uint8);
DECLARE_FUNCTION(SDL_GetRGB, (Uint32, SDL_PixelFormat*, Uint8*, Uint8*, Uint8* ), void);
DECLARE_FUNCTION(SDL_GetRGBA, (Uint32, SDL_PixelFormat*, Uint8*, Uint8*, Uint8*, Uint8* ), void);
DECLARE_FUNCTION(SDL_GetTicks ,(void), Uint32);
DECLARE_FUNCTION(SDL_GetVideoSurface, (void), SDL_Surface* );
DECLARE_FUNCTION(SDL_GL_GetAttribute, (SDL_GLattr, int* ), int);
DECLARE_FUNCTION(SDL_GL_GetProcAddress, (const char*), void*);
DECLARE_FUNCTION(SDL_GL_LoadLibrary, (const char *path), int);
DECLARE_FUNCTION(SDL_GL_SetAttribute, (SDL_GLattr, int), int);
DECLARE_FUNCTION(SDL_GL_SwapBuffers, (void), void);
DECLARE_FUNCTION(SDL_Init, (Uint32), int);
DECLARE_FUNCTION(SDL_InitSubSystem, (Uint32), int);
DECLARE_FUNCTION(SDL_LoadBMP_RW, (SDL_RWops*, int), SDL_Surface* );
DECLARE_FUNCTION(SDL_LoadWAV_RW, (SDL_RWops*, int, SDL_AudioSpec*, Uint8**, Uint32* ), SDL_AudioSpec* );
DECLARE_FUNCTION(SDL_LockAudio, (void), void);
DECLARE_FUNCTION(SDL_LockSurface, (SDL_Surface* ), int);
DECLARE_FUNCTION(SDL_MapRGB, (const SDL_PixelFormat* const, const Uint8, const Uint8, const Uint8), Uint32);
DECLARE_FUNCTION(SDL_MapRGBA, (const SDL_PixelFormat* const, const Uint8, const Uint8, const Uint8, const Uint8), Uint32);
DECLARE_FUNCTION(SDL_MixAudio, (Uint8*, Uint8*, Uint32, int), void);
DECLARE_FUNCTION(SDL_OpenAudio, (SDL_AudioSpec*, SDL_AudioSpec* ), int);
DECLARE_FUNCTION(SDL_PauseAudio, (int), void);
DECLARE_FUNCTION(SDL_PollEvent, (SDL_Event* ), int);
DECLARE_FUNCTION(SDL_PumpEvents, (void), void);
DECLARE_FUNCTION(SDL_PushEvent, (SDL_UserEvent* ), int);
DECLARE_FUNCTION(SDL_Quit, (void), void);
DECLARE_FUNCTION(SDL_RWFromConstMem, (const void*, int), SDL_RWops* );
DECLARE_FUNCTION(SDL_RWFromFile, (char*, char* ), SDL_RWops* );
DECLARE_FUNCTION(SDL_RWFromMem, (void*, int), SDL_RWops* );
DECLARE_FUNCTION(SDL_SaveBMP_RW, (SDL_Surface*, SDL_RWops*, int), int);
DECLARE_FUNCTION(SDL_SetAlpha, (SDL_Surface*, Uint32, Uint8), int);
DECLARE_FUNCTION(SDL_SetClipRect, (SDL_Surface*, const SDL_Rect* ), SDL_bool);
DECLARE_FUNCTION(SDL_SetColorKey, (SDL_Surface*, Uint32, Uint32), int);
DECLARE_FUNCTION(SDL_SetColors, (SDL_Surface*, SDL_Color*, int, int), int);
DECLARE_FUNCTION(SDL_SetModState, (int), void);
DECLARE_FUNCTION(SDL_SetVideoMode,(int, int, int, Uint32), SDL_Surface* );
DECLARE_FUNCTION(SDL_ShowCursor, (int), int);
DECLARE_FUNCTION(SDL_UnlockAudio, (void), void);
DECLARE_FUNCTION(SDL_UnlockSurface, (SDL_Surface* ), void);
DECLARE_FUNCTION(SDL_UpdateRect, (SDL_Surface*, Sint32, Sint32, Uint32, Uint32), void);
DECLARE_FUNCTION(SDL_UpdateRects, (SDL_Surface*, int, SDL_Rect* ), void);
DECLARE_FUNCTION(SDL_UpperBlit, (SDL_Surface*, SDL_Rect*, SDL_Surface*, SDL_Rect* ), int);
DECLARE_FUNCTION(SDL_VideoModeOK, (int, int, int, Uint32), int);
DECLARE_FUNCTION(SDL_WaitEvent, (SDL_Event* ), int);
DECLARE_FUNCTION(SDL_WarpMouse, (Uint16 , Uint16), void);
DECLARE_FUNCTION(SDL_WM_GetCaption, (char**, char** ), void);
DECLARE_FUNCTION(SDL_WM_GrabInput, (int), int);
DECLARE_FUNCTION(SDL_WM_IconifyWindow, (void), int);
DECLARE_FUNCTION(SDL_WM_SetCaption, (char*, char* ), void);
DECLARE_FUNCTION(SDL_WM_SetIcon, (SDL_Surface*, Uint8* ), void);
DECLARE_FUNCTION(SDL_WM_ToggleFullScreen, (SDL_Surface* ), int);

/* OpenGL functions */
DECLARE_FUNCTION(glAccum, (int, float), void);
DECLARE_FUNCTION(glActiveTexture, (int), void);
DECLARE_FUNCTION(glAlphaFunc, (int, float), void);
DECLARE_FUNCTION(glAreTexturesResident, (int, int*, int*), int);
DECLARE_FUNCTION(glArrayElement, (int), void);
DECLARE_FUNCTION(glAttachShader, (int, int), void);
DECLARE_FUNCTION(glBegin, (int), void);
DECLARE_FUNCTION(glBeginQuery, (int, int), void);
DECLARE_FUNCTION(glBindAttribLocation, (int, int, char*), void);
DECLARE_FUNCTION(glBindBuffer, (int, int), void);
DECLARE_FUNCTION(glBindTexture, (int, int), void);
DECLARE_FUNCTION(glBitmap, (int, int, float, float, float, float, char*), void);
DECLARE_FUNCTION(glBlendColor, (float, float, float, float), void);
DECLARE_FUNCTION(glBlendEquation, (int), void);
DECLARE_FUNCTION(glBlendEquationSeparate, (int, int), void);
DECLARE_FUNCTION(glBlendFunc, (int, int), void);
DECLARE_FUNCTION(glBlendFuncSeparate, (int, int, int, int), void);
DECLARE_FUNCTION(glBufferData, (int, int, void*, int), void);
DECLARE_FUNCTION(glBufferSubData, (int, int, int, void*), void);
DECLARE_FUNCTION(glCallList, (int), void);
DECLARE_FUNCTION(glCallLists, (int, int, void*), void);
DECLARE_FUNCTION(glClear, (unsigned int), void);
DECLARE_FUNCTION(glClearAccum, (float, float, float, float), void);
DECLARE_FUNCTION(glClearColor, (float, float, float, float), void);
DECLARE_FUNCTION(glClearDepth, (double), void);
DECLARE_FUNCTION(glClearIndex, (float), void);
DECLARE_FUNCTION(glClearStencil, (int), void);
DECLARE_FUNCTION(glClientActiveTexture, (int), void);
DECLARE_FUNCTION(glClipPlane, (int, double*), void);
DECLARE_FUNCTION(glColor3d, (double, double, double), void);
DECLARE_FUNCTION(glColor4d, (double, double, double, double), void);
DECLARE_FUNCTION(glColorMask, (int, int, int, int), void);
DECLARE_FUNCTION(glColorMaterial, (int, int), void);
DECLARE_FUNCTION(glColorPointer, (int, int, int, void*), void);
DECLARE_FUNCTION(glCompileShader, (int), void);
DECLARE_FUNCTION(glCompressedTexImage1D, (int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCompressedTexImage2D, (int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCompressedTexImage3D, (int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCompressedTexSubImage1D, (int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCompressedTexSubImage2D, (int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCompressedTexSubImage3D, (int, int, int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glCopyPixels, (int, int, int, int, int), void);
DECLARE_FUNCTION(glCopyTexImage1D, (int, int, int, int, int, int, int), void);
DECLARE_FUNCTION(glCopyTexImage2D, (int, int, int, int, int, int, int, int), void);
DECLARE_FUNCTION(glCopyTexSubImage1D, (int, int, int, int, int, int), void);
DECLARE_FUNCTION(glCopyTexSubImage2D, (int, int, int, int, int, int, int, int), void);
DECLARE_FUNCTION(glCopyTexSubImage3D, (int, int, int, int, int, int, int, int, int), void);
DECLARE_FUNCTION(glCreateProgram, (), int);
DECLARE_FUNCTION(glCreateShader, (int), int);
DECLARE_FUNCTION(glCullFace, (int), void);
DECLARE_FUNCTION(glDeleteBuffers, (int, int*), void);
DECLARE_FUNCTION(glDeleteLists, (int, int), void);
DECLARE_FUNCTION(glDeleteProgram, (int), void);
DECLARE_FUNCTION(glDeleteQueries, (int, int*), void);
DECLARE_FUNCTION(glDeleteShader, (int), void);
DECLARE_FUNCTION(glDeleteTextures, (int, int*), void);
DECLARE_FUNCTION(glDepthFunc, (int), void);
DECLARE_FUNCTION(glDepthMask, (int), void);
DECLARE_FUNCTION(glDepthRange, (double, double), void);
DECLARE_FUNCTION(glDetachShader, (int, int), void);
DECLARE_FUNCTION(glDisable, (int), void);
DECLARE_FUNCTION(glDisableClientState, (int), void);
DECLARE_FUNCTION(glDisableVertexAttribArray, (int), void);
DECLARE_FUNCTION(glDrawArrays, (int, int, int), void);
DECLARE_FUNCTION(glDrawBuffer, (int), void);
DECLARE_FUNCTION(glDrawBuffers, (int, int*), void);
DECLARE_FUNCTION(glDrawElements, (int, int, int, void*), void);
DECLARE_FUNCTION(glDrawPixels, (int, int, int, int, void*), void);
DECLARE_FUNCTION(glDrawRangeElements, (int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glEdgeFlag, (int), void);
DECLARE_FUNCTION(glEdgeFlagPointer, (int, void*), void);
DECLARE_FUNCTION(glEnable, (int), void);
DECLARE_FUNCTION(glEnableClientState, (int), void);
DECLARE_FUNCTION(glEnableVertexAttribArray, (int), void);
DECLARE_FUNCTION(glEnd, (), void);
DECLARE_FUNCTION(glEndList, (), void);
DECLARE_FUNCTION(glEndQuery, (int), void);
DECLARE_FUNCTION(glEvalCoord1d, (double), void);
DECLARE_FUNCTION(glEvalCoord2d, (double, double), void);
DECLARE_FUNCTION(glEvalMesh1, (int, int, int), void);
DECLARE_FUNCTION(glEvalMesh2, (int, int, int, int, int), void);
DECLARE_FUNCTION(glEvalPoint1, (int), void);
DECLARE_FUNCTION(glEvalPoint2, (int, int), void);
DECLARE_FUNCTION(glFeedbackBuffer, (int, int, float*), void);
DECLARE_FUNCTION(glFinish, (), void);
DECLARE_FUNCTION(glFlush, (), void);
DECLARE_FUNCTION(glFogCoordPointer, (int, int, void*), void);
DECLARE_FUNCTION(glFogCoordd, (double), void);
DECLARE_FUNCTION(glFogf, (int, float), void);
DECLARE_FUNCTION(glFrontFace, (int), void);
DECLARE_FUNCTION(glFrustum, (double, double, double, double, double, double), void);
DECLARE_FUNCTION(glGenBuffers, (int, int*), void);
DECLARE_FUNCTION(glGenLists, (int), int);
DECLARE_FUNCTION(glGenQueries, (int, int*), void);
DECLARE_FUNCTION(glGenTextures, (int, int*), void);
DECLARE_FUNCTION(glGetActiveAttrib, (int, int, int, int*, int*, int*, char*), void);
DECLARE_FUNCTION(glGetActiveUniform, (int, int, int, int*, int*, int*, char*), void);
DECLARE_FUNCTION(glGetAttachedShaders, (int, int, int*, int*), void);
DECLARE_FUNCTION(glGetAttribLocation, (int, char*), int);
DECLARE_FUNCTION(glGetBooleanv, (int, int*), void);
DECLARE_FUNCTION(glGetBufferParameteriv, (int, int, int*), void);
DECLARE_FUNCTION(glGetBufferPointerv, (int, int, void**), void);
DECLARE_FUNCTION(glGetBufferSubData, (int, int, int, void*), void);
DECLARE_FUNCTION(glGetClipPlane, (int, double*), void);
DECLARE_FUNCTION(glGetCompressedTexImage, (int, int, void*), void);
DECLARE_FUNCTION(glGetDoublev, (int, double*), void);
DECLARE_FUNCTION(glGetError, (), int);
DECLARE_FUNCTION(glGetFloatv, (int, float*), void);
DECLARE_FUNCTION(glGetIntegerv, (int, int*), void);
DECLARE_FUNCTION(glGetLightfv, (int, int, float*), void);
DECLARE_FUNCTION(glGetMapdv, (int, int, double*), void);
DECLARE_FUNCTION(glGetMaterialfv, (int, int, float*), void);
DECLARE_FUNCTION(glGetPixelMapfv, (int, float*), void);
DECLARE_FUNCTION(glGetPointerv, (int, void**), void);
DECLARE_FUNCTION(glGetPolygonStipple, (unsigned char*), void);
DECLARE_FUNCTION(glGetProgramInfoLog, (int, int, int*, char*), void);
DECLARE_FUNCTION(glGetProgramiv, (int, int, int*), void);
DECLARE_FUNCTION(glGetQueryObjectiv, (int, int, int*), void);
DECLARE_FUNCTION(glGetQueryiv, (int, int, int*), void);
DECLARE_FUNCTION(glGetShaderInfoLog, (int, int, int*, char*), void);
DECLARE_FUNCTION(glGetShaderSource, (int, int, int*, char*), void);
DECLARE_FUNCTION(glGetShaderiv, (int, int, int*), void);
DECLARE_FUNCTION(glGetString, (int), char*);
DECLARE_FUNCTION(glGetTexEnvfv, (int, int, float*), void);
DECLARE_FUNCTION(glGetTexEnviv, (int, int, int*), void);
DECLARE_FUNCTION(glGetTexGendv, (int, int, double*), void);
DECLARE_FUNCTION(glGetTexImage, (int, int, int, int, void*), void);
DECLARE_FUNCTION(glGetTexLevelParameterfv, (int, int, int, float*), void);
DECLARE_FUNCTION(glGetTexParameterfv, (int, int, float*), void);
DECLARE_FUNCTION(glGetUniformLocation, (int, char*), int);
DECLARE_FUNCTION(glGetUniformfv, (int, int, float*), void);
DECLARE_FUNCTION(glGetVertexAttribdv, (int, int, double*), void);
DECLARE_FUNCTION(glHint, (int, int), void);
DECLARE_FUNCTION(glIndexMask, (int), void);
DECLARE_FUNCTION(glIndexPointer, (int, int, void*), void);
DECLARE_FUNCTION(glIndexd, (double), void);
DECLARE_FUNCTION(glInitNames, (), void);
DECLARE_FUNCTION(glInterleavedArrays, (int, int, void*), void);
DECLARE_FUNCTION(glIsBuffer, (int), int);
DECLARE_FUNCTION(glIsEnabled, (int), int);
DECLARE_FUNCTION(glIsList, (int), int);
DECLARE_FUNCTION(glIsProgram, (int), int);
DECLARE_FUNCTION(glIsQuery, (int), int);
DECLARE_FUNCTION(glIsShader, (int), int);
DECLARE_FUNCTION(glIsTexture, (int), int);
DECLARE_FUNCTION(glLightModelf, (int, float), void);
DECLARE_FUNCTION(glLightf, (int, int, float), void);
DECLARE_FUNCTION(glLineStipple, (int, int), void);
DECLARE_FUNCTION(glLineWidth, (float), void);
DECLARE_FUNCTION(glLinkProgram, (int), void);
DECLARE_FUNCTION(glListBase, (int), void);
DECLARE_FUNCTION(glLoadIdentity, (), void);
DECLARE_FUNCTION(glLoadMatrixd, (double*), void);
DECLARE_FUNCTION(glLoadName, (int), void);
DECLARE_FUNCTION(glLoadTransposeMatrixd, (double*), void);
DECLARE_FUNCTION(glLogicOp, (int), void);
DECLARE_FUNCTION(glMap1d, (int, double, double, int, int, double*), void);
DECLARE_FUNCTION(glMap2d, (int, double, double, int, int, double, double, int, int, double*), void);
DECLARE_FUNCTION(glMapBuffer, (int, int), void*);
DECLARE_FUNCTION(glMapGrid1d, (int, double, double), void);
DECLARE_FUNCTION(glMapGrid2d, (int, double, double, int, double, double), void);
DECLARE_FUNCTION(glMaterialf, (int, int, float), void);
DECLARE_FUNCTION(glMatrixMode, (int), void);
DECLARE_FUNCTION(glMultMatrixd, (double*), void);
DECLARE_FUNCTION(glMultTransposeMatrixd, (double*), void);
DECLARE_FUNCTION(glMultiDrawArrays, (int, int*, int*, int), void);
DECLARE_FUNCTION(glMultiDrawElements, (int, int*, int, void**, int), void);
DECLARE_FUNCTION(glMultiTexCoord1d, (int, double), void);
DECLARE_FUNCTION(glMultiTexCoord2d, (int, double, double), void);
DECLARE_FUNCTION(glMultiTexCoord3d, (int, double, double, double), void);
DECLARE_FUNCTION(glMultiTexCoord4d, (int, double, double, double, double), void);
DECLARE_FUNCTION(glNewList, (int, int), void);
DECLARE_FUNCTION(glNormal3d, (double, double, double), void);
DECLARE_FUNCTION(glNormalPointer, (int, int, void*), void);
DECLARE_FUNCTION(glOrtho, (double, double, double, double, double, double), void);
DECLARE_FUNCTION(glPassThrough, (float), void);
DECLARE_FUNCTION(glPixelMapfv, (int, int, float*), void);
DECLARE_FUNCTION(glPixelStoref, (int, float), void);
DECLARE_FUNCTION(glPixelTransferf, (int, float), void);
DECLARE_FUNCTION(glPixelZoom, (float, float), void);
DECLARE_FUNCTION(glPointParameterf, (int, float), void);
DECLARE_FUNCTION(glPointSize, (float), void);
DECLARE_FUNCTION(glPolygonMode, (int, int), void);
DECLARE_FUNCTION(glPolygonOffset, (float, float), void);
DECLARE_FUNCTION(glPolygonStipple, (char*), void);
DECLARE_FUNCTION(glPopAttrib, (), void);
DECLARE_FUNCTION(glPopClientAttrib, (), void);
DECLARE_FUNCTION(glPopMatrix, (), void);
DECLARE_FUNCTION(glPopName, (), void);
DECLARE_FUNCTION(glPrioritizeTextures, (int, int*, float*), void);
DECLARE_FUNCTION(glPushAttrib, (unsigned int), void);
DECLARE_FUNCTION(glPushClientAttrib, (unsigned int), void);
DECLARE_FUNCTION(glPushMatrix, (), void);
DECLARE_FUNCTION(glPushName, (int), void);
DECLARE_FUNCTION(glRasterPos2d, (double, double), void);
DECLARE_FUNCTION(glRasterPos3d, (double, double, double), void);
DECLARE_FUNCTION(glRasterPos4d, (double, double, double, double), void);
DECLARE_FUNCTION(glReadBuffer, (int), void);
DECLARE_FUNCTION(glReadPixels, (int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glRectd, (double, double, double, double), void);
DECLARE_FUNCTION(glRenderMode, (int), int);
DECLARE_FUNCTION(glRotated, (double, double, double, double), void);
DECLARE_FUNCTION(glSampleCoverage, (float, int), void);
DECLARE_FUNCTION(glScaled, (double, double, double), void);
DECLARE_FUNCTION(glScissor, (int, int, int, int), void);
DECLARE_FUNCTION(glSecondaryColor3d, (double, double, double), void);
DECLARE_FUNCTION(glSecondaryColorPointer, (int, int, int, void*), void);
DECLARE_FUNCTION(glSelectBuffer, (int, int*), void);
DECLARE_FUNCTION(glShadeModel, (int), void);
DECLARE_FUNCTION(glShaderSource, (int, int, char**, int*), void);
DECLARE_FUNCTION(glStencilFunc, (int, int, int), void);
DECLARE_FUNCTION(glStencilFuncSeparate, (int, int, int, int), void);
DECLARE_FUNCTION(glStencilMask, (int), void);
DECLARE_FUNCTION(glStencilMaskSeparate, (int, int), void);
DECLARE_FUNCTION(glStencilOp, (int, int, int), void);
DECLARE_FUNCTION(glStencilOpSeparate, (int, int, int, int), void);
DECLARE_FUNCTION(glTexCoord1d, (double), void);
DECLARE_FUNCTION(glTexCoord2d, (double, double), void);
DECLARE_FUNCTION(glTexCoord3d, (double, double, double), void);
DECLARE_FUNCTION(glTexCoord4d, (double, double, double, double), void);
DECLARE_FUNCTION(glTexCoordPointer, (int, int, int, void*), void);
DECLARE_FUNCTION(glTexEnvf, (int, int, float), void);
DECLARE_FUNCTION(glTexGend, (int, int, double), void);
DECLARE_FUNCTION(glTexImage1D, (int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTexImage2D, (int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTexImage3D, (int, int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTexParameterf, (int, int, float), void);
DECLARE_FUNCTION(glTexSubImage1D, (int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTexSubImage2D, (int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTexSubImage3D, (int, int, int, int, int, int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glTranslated, (double, double, double), void);
DECLARE_FUNCTION(glUniform1f, (int, float), void);
DECLARE_FUNCTION(glUniform2f, (int, float, float), void);
DECLARE_FUNCTION(glUniform3f, (int, float, float, float), void);
DECLARE_FUNCTION(glUniform4f, (int, float, float, float, float), void);
DECLARE_FUNCTION(glUniformMatrix2fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix2x3fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix2x4fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix3fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix3x2fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix3x4fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix4fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix4x2fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUniformMatrix4x3fv, (int, int, int, float*), void);
DECLARE_FUNCTION(glUnmapBuffer, (int), int);
DECLARE_FUNCTION(glUseProgram, (int), void);
DECLARE_FUNCTION(glValidateProgram, (int), void);
DECLARE_FUNCTION(glVertex2d, (double, double), void);
DECLARE_FUNCTION(glVertex3d, (double, double, double), void);
DECLARE_FUNCTION(glVertex4d, (double, double, double, double), void);
DECLARE_FUNCTION(glVertexAttrib1d, (int, double), void);
DECLARE_FUNCTION(glVertexAttrib2d, (int, double, double), void);
DECLARE_FUNCTION(glVertexAttrib3d, (int, double, double, double), void);
DECLARE_FUNCTION(glVertexAttrib4Nub, (int, int, int, int, int), void);
DECLARE_FUNCTION(glVertexAttrib4d, (int, double, double, double, double), void);
DECLARE_FUNCTION(glVertexAttribPointer, (int, int, int, int, int, void*), void);
DECLARE_FUNCTION(glVertexPointer, (int, int, int, void*), void);
DECLARE_FUNCTION(glViewport, (int, int, int, int), void);
DECLARE_FUNCTION(glWindowPos2d, (double, double), void);
DECLARE_FUNCTION(glWindowPos3d, (double, double, double), void);

void HAL_Quit(void)
{
	FN(SDL_Quit)();
}

void hal_init_sdl (void) {
    LOAD_FUNCTION(libSDL, SDL_BuildAudioCVT);
    LOAD_FUNCTION(libSDL, SDL_CloseAudio);
    LOAD_FUNCTION(libSDL, SDL_ConvertAudio);
    LOAD_FUNCTION(libSDL, SDL_CreateRGBSurface);
    LOAD_FUNCTION(libSDL, SDL_Delay);
    LOAD_FUNCTION(libSDL, SDL_DisplayFormat);
    LOAD_FUNCTION(libSDL, SDL_EnableKeyRepeat);
    LOAD_FUNCTION(libSDL, SDL_EnableUNICODE);
    LOAD_FUNCTION(libSDL, SDL_EventState);
    LOAD_FUNCTION(libSDL, SDL_FillRect);
    LOAD_FUNCTION(libSDL, SDL_Flip);
    LOAD_FUNCTION(libSDL, SDL_FreeSurface);
    LOAD_FUNCTION(libSDL, SDL_FreeWAV);
    LOAD_FUNCTION(libSDL, SDL_GetAppState);
    LOAD_FUNCTION(libSDL, SDL_GetAudioStatus);
    LOAD_FUNCTION(libSDL, SDL_GetError);
    LOAD_FUNCTION(libSDL, SDL_GetKeyName);
    LOAD_FUNCTION(libSDL, SDL_GetModState);
    LOAD_FUNCTION(libSDL, SDL_GetMouseState);
    LOAD_FUNCTION(libSDL, SDL_GetRGB);
    LOAD_FUNCTION(libSDL, SDL_GetRGBA);
    LOAD_FUNCTION(libSDL, SDL_GetTicks);
    LOAD_FUNCTION(libSDL, SDL_GetVideoSurface);
    LOAD_FUNCTION(libSDL, SDL_GL_GetAttribute);
    LOAD_FUNCTION(libSDL, SDL_GL_GetProcAddress);
    LOAD_FUNCTION(libSDL, SDL_GL_LoadLibrary);
    LOAD_FUNCTION(libSDL, SDL_GL_SetAttribute);
    LOAD_FUNCTION(libSDL, SDL_GL_SwapBuffers);
    LOAD_FUNCTION(libSDL, SDL_Init);
    LOAD_FUNCTION(libSDL, SDL_InitSubSystem);
    LOAD_FUNCTION(libSDL, SDL_LoadBMP_RW);
    LOAD_FUNCTION(libSDL, SDL_LoadWAV_RW);
    LOAD_FUNCTION(libSDL, SDL_LockAudio);
    LOAD_FUNCTION(libSDL, SDL_LockSurface);
    LOAD_FUNCTION(libSDL, SDL_MapRGB);
    LOAD_FUNCTION(libSDL, SDL_MapRGBA);
    LOAD_FUNCTION(libSDL, SDL_MixAudio);
    LOAD_FUNCTION(libSDL, SDL_OpenAudio);
    LOAD_FUNCTION(libSDL, SDL_PauseAudio);
    LOAD_FUNCTION(libSDL, SDL_PollEvent);
    LOAD_FUNCTION(libSDL, SDL_PumpEvents);
    LOAD_FUNCTION(libSDL, SDL_PushEvent);
    LOAD_FUNCTION(libSDL, SDL_Quit);
    LOAD_FUNCTION(libSDL, SDL_RWFromConstMem);
    LOAD_FUNCTION(libSDL, SDL_RWFromFile);
    LOAD_FUNCTION(libSDL, SDL_RWFromMem);
    LOAD_FUNCTION(libSDL, SDL_SaveBMP_RW);
    LOAD_FUNCTION(libSDL, SDL_SetAlpha);
    LOAD_FUNCTION(libSDL, SDL_SetClipRect);
    LOAD_FUNCTION(libSDL, SDL_SetColorKey);
    LOAD_FUNCTION(libSDL, SDL_SetColors);
    LOAD_FUNCTION(libSDL, SDL_SetModState);
    LOAD_FUNCTION(libSDL, SDL_SetVideoMode);
    LOAD_FUNCTION(libSDL, SDL_ShowCursor);
    LOAD_FUNCTION(libSDL, SDL_UnlockAudio);
    LOAD_FUNCTION(libSDL, SDL_UnlockSurface);
    LOAD_FUNCTION(libSDL, SDL_UpdateRect);
    LOAD_FUNCTION(libSDL, SDL_UpdateRects);
    LOAD_FUNCTION(libSDL, SDL_UpperBlit);
    LOAD_FUNCTION(libSDL, SDL_VideoModeOK);
    LOAD_FUNCTION(libSDL, SDL_WaitEvent);
    LOAD_FUNCTION(libSDL, SDL_WarpMouse);
    LOAD_FUNCTION(libSDL, SDL_WM_GetCaption);
    LOAD_FUNCTION(libSDL, SDL_WM_GrabInput);
    LOAD_FUNCTION(libSDL, SDL_WM_IconifyWindow);
    LOAD_FUNCTION(libSDL, SDL_WM_SetCaption);
    LOAD_FUNCTION(libSDL, SDL_WM_SetIcon);
    LOAD_FUNCTION(libSDL, SDL_WM_ToggleFullScreen);
    atexit(HAL_Quit);	
	if (FN(SDL_Init)(SDL_INIT_VIDEO)<0)
	{
		caml_failwith(FN(SDL_GetError)());
	}	
}

void hal_init_gl (const char *path) {
	char *version = NULL;
    
	if(FN(SDL_GL_LoadLibrary)(path) < 0)
	{
		caml_failwith(FN(SDL_GetError)());
	}
    
	LOAD_GL_FUNCTION(glAccum);
	LOAD_GL_FUNCTION(glAlphaFunc);
	LOAD_GL_FUNCTION(glAreTexturesResident);
	LOAD_GL_FUNCTION(glArrayElement);
	LOAD_GL_FUNCTION(glBegin);
	LOAD_GL_FUNCTION(glBindTexture);
	LOAD_GL_FUNCTION(glBitmap);
	LOAD_GL_FUNCTION(glBlendFunc);
	LOAD_GL_FUNCTION(glCallList);
	LOAD_GL_FUNCTION(glCallLists);
	LOAD_GL_FUNCTION(glClear);
	LOAD_GL_FUNCTION(glClearAccum);
	LOAD_GL_FUNCTION(glClearColor);
	LOAD_GL_FUNCTION(glClearDepth);
	LOAD_GL_FUNCTION(glClearIndex);
	LOAD_GL_FUNCTION(glClearStencil);
	LOAD_GL_FUNCTION(glClipPlane);
	LOAD_GL_FUNCTION(glColor3d);
	LOAD_GL_FUNCTION(glColor4d);
	LOAD_GL_FUNCTION(glColorMask);
	LOAD_GL_FUNCTION(glColorMaterial);
	LOAD_GL_FUNCTION(glColorPointer);
	LOAD_GL_FUNCTION(glCopyPixels);
	LOAD_GL_FUNCTION(glCopyTexImage1D);
	LOAD_GL_FUNCTION(glCopyTexImage2D);
	LOAD_GL_FUNCTION(glCopyTexSubImage1D);
	LOAD_GL_FUNCTION(glCopyTexSubImage2D);
	LOAD_GL_FUNCTION(glCullFace);
	LOAD_GL_FUNCTION(glDeleteLists);
	LOAD_GL_FUNCTION(glDeleteTextures);
	LOAD_GL_FUNCTION(glDepthFunc);
	LOAD_GL_FUNCTION(glDepthMask);
	LOAD_GL_FUNCTION(glDepthRange);
	LOAD_GL_FUNCTION(glDisable);
	LOAD_GL_FUNCTION(glDisableClientState);
	LOAD_GL_FUNCTION(glDrawArrays);
	LOAD_GL_FUNCTION(glDrawBuffer);
	LOAD_GL_FUNCTION(glDrawElements);
	LOAD_GL_FUNCTION(glDrawPixels);
	LOAD_GL_FUNCTION(glEdgeFlag);
	LOAD_GL_FUNCTION(glEdgeFlagPointer);
	LOAD_GL_FUNCTION(glEnable);
	LOAD_GL_FUNCTION(glEnableClientState);
	LOAD_GL_FUNCTION(glEnd);
	LOAD_GL_FUNCTION(glEndList);
	LOAD_GL_FUNCTION(glEvalCoord1d);
	LOAD_GL_FUNCTION(glEvalCoord2d);
	LOAD_GL_FUNCTION(glEvalMesh1);
	LOAD_GL_FUNCTION(glEvalMesh2);
	LOAD_GL_FUNCTION(glEvalPoint1);
	LOAD_GL_FUNCTION(glEvalPoint2);
	LOAD_GL_FUNCTION(glFeedbackBuffer);
	LOAD_GL_FUNCTION(glFinish);
	LOAD_GL_FUNCTION(glFlush);
	LOAD_GL_FUNCTION(glFogf);
	LOAD_GL_FUNCTION(glFrontFace);
	LOAD_GL_FUNCTION(glFrustum);
	LOAD_GL_FUNCTION(glGenLists);
	LOAD_GL_FUNCTION(glGenTextures);
	LOAD_GL_FUNCTION(glGetBooleanv);
	LOAD_GL_FUNCTION(glGetClipPlane);
	LOAD_GL_FUNCTION(glGetDoublev);
	LOAD_GL_FUNCTION(glGetError);
	LOAD_GL_FUNCTION(glGetFloatv);
	LOAD_GL_FUNCTION(glGetIntegerv);
	LOAD_GL_FUNCTION(glGetLightfv);
	LOAD_GL_FUNCTION(glGetMapdv);
	LOAD_GL_FUNCTION(glGetMaterialfv);
	LOAD_GL_FUNCTION(glGetPixelMapfv);
	LOAD_GL_FUNCTION(glGetPointerv);
	LOAD_GL_FUNCTION(glGetPolygonStipple);
	LOAD_GL_FUNCTION(glGetString);
	LOAD_GL_FUNCTION(glGetTexEnvfv);
	LOAD_GL_FUNCTION(glGetTexEnviv);
	LOAD_GL_FUNCTION(glGetTexGendv);
	LOAD_GL_FUNCTION(glGetTexImage);
	LOAD_GL_FUNCTION(glGetTexLevelParameterfv);
	LOAD_GL_FUNCTION(glGetTexParameterfv);
	LOAD_GL_FUNCTION(glHint);
	LOAD_GL_FUNCTION(glIndexMask);
	LOAD_GL_FUNCTION(glIndexPointer);
	LOAD_GL_FUNCTION(glIndexd);
	LOAD_GL_FUNCTION(glInitNames);
	LOAD_GL_FUNCTION(glInterleavedArrays);
	LOAD_GL_FUNCTION(glIsEnabled);
	LOAD_GL_FUNCTION(glIsList);
	LOAD_GL_FUNCTION(glIsTexture);
	LOAD_GL_FUNCTION(glLightModelf);
	LOAD_GL_FUNCTION(glLightf);
	LOAD_GL_FUNCTION(glLineStipple);
	LOAD_GL_FUNCTION(glLineWidth);
	LOAD_GL_FUNCTION(glListBase);
	LOAD_GL_FUNCTION(glLoadIdentity);
	LOAD_GL_FUNCTION(glLoadMatrixd);
	LOAD_GL_FUNCTION(glLoadName);
	LOAD_GL_FUNCTION(glLogicOp);
	LOAD_GL_FUNCTION(glMap1d);
	LOAD_GL_FUNCTION(glMap2d);
	LOAD_GL_FUNCTION(glMapGrid1d);
	LOAD_GL_FUNCTION(glMapGrid2d);
	LOAD_GL_FUNCTION(glMaterialf);
	LOAD_GL_FUNCTION(glMatrixMode);
	LOAD_GL_FUNCTION(glMultMatrixd);
	LOAD_GL_FUNCTION(glNewList);
	LOAD_GL_FUNCTION(glNormal3d);
	LOAD_GL_FUNCTION(glNormalPointer);
	LOAD_GL_FUNCTION(glOrtho);
	LOAD_GL_FUNCTION(glPassThrough);
	LOAD_GL_FUNCTION(glPixelMapfv);
	LOAD_GL_FUNCTION(glPixelStoref);
	LOAD_GL_FUNCTION(glPixelTransferf);
	LOAD_GL_FUNCTION(glPixelZoom);
	LOAD_GL_FUNCTION(glPointSize);
	LOAD_GL_FUNCTION(glPolygonMode);
	LOAD_GL_FUNCTION(glPolygonOffset);
	LOAD_GL_FUNCTION(glPolygonStipple);
	LOAD_GL_FUNCTION(glPopAttrib);
	LOAD_GL_FUNCTION(glPopClientAttrib);
	LOAD_GL_FUNCTION(glPopMatrix);
	LOAD_GL_FUNCTION(glPopName);
	LOAD_GL_FUNCTION(glPrioritizeTextures);
	LOAD_GL_FUNCTION(glPushAttrib);
	LOAD_GL_FUNCTION(glPushClientAttrib);
	LOAD_GL_FUNCTION(glPushMatrix);
	LOAD_GL_FUNCTION(glPushName);
	LOAD_GL_FUNCTION(glRasterPos2d);
	LOAD_GL_FUNCTION(glRasterPos3d);
	LOAD_GL_FUNCTION(glRasterPos4d);
	LOAD_GL_FUNCTION(glReadBuffer);
	LOAD_GL_FUNCTION(glReadPixels);
	LOAD_GL_FUNCTION(glRectd);
	LOAD_GL_FUNCTION(glRenderMode);
	LOAD_GL_FUNCTION(glRotated);
	LOAD_GL_FUNCTION(glScaled);
	LOAD_GL_FUNCTION(glScissor);
	LOAD_GL_FUNCTION(glSelectBuffer);
	LOAD_GL_FUNCTION(glShadeModel);
	LOAD_GL_FUNCTION(glStencilFunc);
	LOAD_GL_FUNCTION(glStencilMask);
	LOAD_GL_FUNCTION(glStencilOp);
	LOAD_GL_FUNCTION(glTexCoord1d);
	LOAD_GL_FUNCTION(glTexCoord2d);
	LOAD_GL_FUNCTION(glTexCoord3d);
	LOAD_GL_FUNCTION(glTexCoord4d);
	LOAD_GL_FUNCTION(glTexCoordPointer);
	LOAD_GL_FUNCTION(glTexEnvf);
	LOAD_GL_FUNCTION(glTexGend);
	LOAD_GL_FUNCTION(glTexImage1D);
	LOAD_GL_FUNCTION(glTexImage2D);
	LOAD_GL_FUNCTION(glTexParameterf);
	LOAD_GL_FUNCTION(glTexSubImage1D);
	LOAD_GL_FUNCTION(glTexSubImage2D);
	LOAD_GL_FUNCTION(glTranslated);
	LOAD_GL_FUNCTION(glVertex2d);
	LOAD_GL_FUNCTION(glVertex3d);
	LOAD_GL_FUNCTION(glVertex4d);
	LOAD_GL_FUNCTION(glVertexPointer);
	LOAD_GL_FUNCTION(glViewport);
	
    version = FN(glGetString)(GL_VERSION);
    
	if(version && strcmp(version, "1.2") >= 0)
	{
		LOAD_GL_FUNCTION(glDrawRangeElements);
		LOAD_GL_FUNCTION(glTexImage3D);
		LOAD_GL_FUNCTION(glTexSubImage3D);
		LOAD_GL_FUNCTION(glCopyTexSubImage3D);
	}
	
	if(version && strcmp(version, "1.3") >= 0)
	{
		LOAD_GL_FUNCTION(glActiveTexture);
		LOAD_GL_FUNCTION(glClientActiveTexture);
		LOAD_GL_FUNCTION(glCompressedTexImage1D);
		LOAD_GL_FUNCTION(glCompressedTexImage2D);
		LOAD_GL_FUNCTION(glCompressedTexImage3D);
		LOAD_GL_FUNCTION(glCompressedTexSubImage1D);
		LOAD_GL_FUNCTION(glCompressedTexSubImage2D);
		LOAD_GL_FUNCTION(glCompressedTexSubImage3D);
		LOAD_GL_FUNCTION(glGetCompressedTexImage);
		LOAD_GL_FUNCTION(glLoadTransposeMatrixd);
		LOAD_GL_FUNCTION(glMultTransposeMatrixd);
		LOAD_GL_FUNCTION(glMultiTexCoord1d);
		LOAD_GL_FUNCTION(glMultiTexCoord2d);
		LOAD_GL_FUNCTION(glMultiTexCoord3d);
		LOAD_GL_FUNCTION(glMultiTexCoord4d);
		LOAD_GL_FUNCTION(glSampleCoverage);
	}
	
	if(version && strcmp(version, "1.4") >= 0)
	{
		LOAD_GL_FUNCTION(glBlendEquation);
		LOAD_GL_FUNCTION(glBlendColor);
		LOAD_GL_FUNCTION(glFogCoordd);
		LOAD_GL_FUNCTION(glFogCoordPointer);
		LOAD_GL_FUNCTION(glMultiDrawArrays);
		LOAD_GL_FUNCTION(glMultiDrawElements);
		LOAD_GL_FUNCTION(glPointParameterf);
		LOAD_GL_FUNCTION(glSecondaryColor3d);
		LOAD_GL_FUNCTION(glSecondaryColorPointer);
		LOAD_GL_FUNCTION(glBlendFuncSeparate);
		LOAD_GL_FUNCTION(glWindowPos2d);
		LOAD_GL_FUNCTION(glWindowPos3d);
	}
	
	if(version && strcmp(version, "1.5") >= 0)
	{
		LOAD_GL_FUNCTION(glGenQueries);
		LOAD_GL_FUNCTION(glDeleteQueries);
		LOAD_GL_FUNCTION(glIsQuery);
		LOAD_GL_FUNCTION(glBeginQuery);
		LOAD_GL_FUNCTION(glEndQuery);
		LOAD_GL_FUNCTION(glGetQueryiv);
		LOAD_GL_FUNCTION(glGetQueryObjectiv);
		LOAD_GL_FUNCTION(glBindBuffer);
		LOAD_GL_FUNCTION(glDeleteBuffers);
		LOAD_GL_FUNCTION(glGenBuffers);
		LOAD_GL_FUNCTION(glIsBuffer);
		LOAD_GL_FUNCTION(glBufferData);
		LOAD_GL_FUNCTION(glBufferSubData);
		LOAD_GL_FUNCTION(glGetBufferSubData);
		LOAD_GL_FUNCTION(glMapBuffer);
		LOAD_GL_FUNCTION(glUnmapBuffer);
		LOAD_GL_FUNCTION(glGetBufferParameteriv);
		LOAD_GL_FUNCTION(glGetBufferPointerv);
	}
	
    if(version && strcmp(version, "2.0") >= 0)
	{
		LOAD_GL_FUNCTION(glBlendEquationSeparate);
		LOAD_GL_FUNCTION(glDrawBuffers);
		LOAD_GL_FUNCTION(glStencilOpSeparate);
		LOAD_GL_FUNCTION(glStencilFuncSeparate);
		LOAD_GL_FUNCTION(glStencilMaskSeparate);
		LOAD_GL_FUNCTION(glAttachShader);
		LOAD_GL_FUNCTION(glBindAttribLocation);
		LOAD_GL_FUNCTION(glCompileShader);
		LOAD_GL_FUNCTION(glCreateProgram);
		LOAD_GL_FUNCTION(glCreateShader);
		LOAD_GL_FUNCTION(glDeleteProgram);
		LOAD_GL_FUNCTION(glDeleteShader);
		LOAD_GL_FUNCTION(glDetachShader);
		LOAD_GL_FUNCTION(glDisableVertexAttribArray);
		LOAD_GL_FUNCTION(glEnableVertexAttribArray);
		LOAD_GL_FUNCTION(glGetActiveAttrib);
		LOAD_GL_FUNCTION(glGetActiveUniform);
		LOAD_GL_FUNCTION(glGetAttachedShaders);
		LOAD_GL_FUNCTION(glGetAttribLocation);
		LOAD_GL_FUNCTION(glGetProgramiv);
		LOAD_GL_FUNCTION(glGetProgramInfoLog);
		LOAD_GL_FUNCTION(glGetShaderiv);
		LOAD_GL_FUNCTION(glGetShaderInfoLog);
		LOAD_GL_FUNCTION(glShaderSource);
		LOAD_GL_FUNCTION(glGetUniformLocation);
		LOAD_GL_FUNCTION(glGetUniformfv);
		LOAD_GL_FUNCTION(glGetVertexAttribdv);
		LOAD_GL_FUNCTION(glIsProgram);
		LOAD_GL_FUNCTION(glIsShader);
		LOAD_GL_FUNCTION(glLinkProgram);
		LOAD_GL_FUNCTION(glGetShaderSource);
		LOAD_GL_FUNCTION(glUseProgram);
		LOAD_GL_FUNCTION(glUniform1f);
		LOAD_GL_FUNCTION(glUniform2f);
		LOAD_GL_FUNCTION(glUniform3f);
		LOAD_GL_FUNCTION(glUniform4f);
		LOAD_GL_FUNCTION(glUniformMatrix2fv);
		LOAD_GL_FUNCTION(glUniformMatrix3fv);
		LOAD_GL_FUNCTION(glUniformMatrix4fv);
		LOAD_GL_FUNCTION(glValidateProgram);
		LOAD_GL_FUNCTION(glVertexAttrib1d);
		LOAD_GL_FUNCTION(glVertexAttrib2d);
		LOAD_GL_FUNCTION(glVertexAttrib3d);
		LOAD_GL_FUNCTION(glVertexAttrib4Nub);
		LOAD_GL_FUNCTION(glVertexAttrib4d);
		LOAD_GL_FUNCTION(glVertexAttribPointer);
	}
	
    if(version && strcmp(version, "2.1") >= 0)
	{
		LOAD_GL_FUNCTION(glUniformMatrix2x3fv);
		LOAD_GL_FUNCTION(glUniformMatrix2x4fv);
		LOAD_GL_FUNCTION(glUniformMatrix3x2fv);
		LOAD_GL_FUNCTION(glUniformMatrix3x4fv);
		LOAD_GL_FUNCTION(glUniformMatrix4x2fv);
		LOAD_GL_FUNCTION(glUniformMatrix4x3fv);
	}
}


/*******************************************************************************
                        EXPORTED HAL FUNCTIONS
*******************************************************************************/


value hal_init(value p_path)
{
    CAMLparam1(p_path);
    char *path = caml_string_length(p_path) ? String_val(p_path) : NULL;
    
    /* Init SDL and OpenGL */
    hal_init_sdl();
    hal_init_gl(path);
    
    /* Enable defaults */
    FN(SDL_EnableUNICODE)(1);
    
    CAMLreturn(Val_unit);
}


/*******************************************************************************
                        LIBSDL FUNCTIONS
*******************************************************************************/


/************************* Audio **********************************************/

static SDL_AudioSpec g_audioSpec;

void HAL_SDL_mix_callback(void *userdata, Uint8 *data, int len)
{
    caml_callback( *caml_named_value("mix_callback"),
    alloc_bigarray_dims(BIGARRAY_UINT16 | BIGARRAY_C_LAYOUT, 1, data, len/2));
}

value hal_init_sound(value freq, value samples)
{
    CAMLparam2(freq, samples);
    SDL_AudioSpec l_obtainedSpec;
    if( FN(SDL_InitSubSystem)( SDL_INIT_AUDIO ) < 0)
    {
        caml_failwith(FN(SDL_GetError)());
    }
    g_audioSpec.freq = Int_val(freq);
    g_audioSpec.format = AUDIO_S16;
    g_audioSpec.channels = 2;
    g_audioSpec.samples = Int_val(samples);
    g_audioSpec.fncallback =  HAL_SDL_mix_callback;
    if( FN(SDL_OpenAudio)(&g_audioSpec, &l_obtainedSpec) < 0)
    {
        caml_failwith(FN(SDL_GetError)());
    }
    CAMLreturn(Val_unit);
}


value hal_load_wav(value wav)
{
    CAMLparam1(wav);
    CAMLlocal1 (cvt_data_tmp);
    Uint8 *data, *cvt_data_final;
    Uint32 len;
    SDL_AudioSpec wav_spec;
    SDL_AudioCVT  wav_cvt;
    int nlen = 0;
	SDL_RWops *rw = FN(SDL_RWFromConstMem)(String_val(wav), caml_string_length(wav));
    if( FN(SDL_LoadWAV_RW)(rw, 1, &wav_spec, &data, &len) == NULL)
    {
        caml_failwith(FN(SDL_GetError)());
    }
    if( FN(SDL_BuildAudioCVT)( &wav_cvt,
        wav_spec.format, wav_spec.channels, wav_spec.freq,
        g_audioSpec.format, g_audioSpec.channels, g_audioSpec.freq) == -1)
    {
        FN(SDL_FreeWAV)(data);
        caml_failwith(FN(SDL_GetError)());
    }
    cvt_data_tmp = caml_alloc_string(len * wav_cvt.len_mult);
    wav_cvt.buf = (Uint8*)String_val(cvt_data_tmp);
    wav_cvt.len = len;
    memcpy(wav_cvt.buf, data, len);
    FN(SDL_FreeWAV)(data);
    FN(SDL_ConvertAudio)(&wav_cvt);
    nlen = wav_cvt.len * wav_cvt.len_ratio;
    cvt_data_final = malloc(nlen);
    memcpy(cvt_data_final, String_val(cvt_data_tmp), nlen);
    CAMLreturn(alloc_bigarray_dims(BIGARRAY_UINT16 | BIGARRAY_C_LAYOUT, 1, cvt_data_final, nlen/2));
}

value hal_mute(value on)
{
    CAMLparam1(on);
    FN(SDL_PauseAudio)(Bool_val(on)? 1 : 0);
    CAMLreturn(Val_unit);
}

value hal_lock_audio (value u) {
	CAMLparam1(u);
	FN(SDL_LockAudio)();
    CAMLreturn(Val_unit);
}

value hal_unlock_audio (value u) {
	CAMLparam1(u);
	FN(SDL_UnlockAudio)();
    CAMLreturn(Val_unit);
}


/************************* End Audio ******************************************/


/************************* Events *********************************************/

int key_to_ml_enum(SDLKey key)
{
    switch(key)
    {
	    case SDLK_FIRST		: return 1  ; break;
	    case SDLK_BACKSPACE	: return 2  ; break;
	    case SDLK_TAB		: return 3  ; break;
	    case SDLK_CLEAR		: return 4  ; break;
	    case SDLK_RETURN	: return 5  ; break;
	    case SDLK_PAUSE		: return 6  ; break;
	    case SDLK_ESCAPE	: return 7  ; break;
	    case SDLK_SPACE		: return 8  ; break;
	    case SDLK_EXCLAIM	: return 9  ; break;
	    case SDLK_QUOTEDBL	: return 10 ; break;
	    case SDLK_HASH		: return 11 ; break;
	    case SDLK_DOLLAR	: return 12 ; break;
	    case SDLK_AMPERSAND	: return 13 ; break;
	    case SDLK_QUOTE		: return 14 ; break;
	    case SDLK_LEFTPAREN	: return 15 ; break;
	    case SDLK_RIGHTPAREN: return 16 ; break;
	    case SDLK_ASTERISK	: return 17 ; break;
	    case SDLK_PLUS		: return 18 ; break;
	    case SDLK_COMMA		: return 19 ; break;
	    case SDLK_MINUS		: return 20 ; break;
	    case SDLK_PERIOD	: return 21 ; break;
	    case SDLK_SLASH		: return 22 ; break;
	    case SDLK_0			: return 23 ; break;
	    case SDLK_1			: return 24 ; break;
	    case SDLK_2			: return 25 ; break;
	    case SDLK_3			: return 26 ; break;
	    case SDLK_4			: return 27 ; break;
	    case SDLK_5			: return 28 ; break;
	    case SDLK_6			: return 29 ; break;
	    case SDLK_7			: return 30 ; break;
	    case SDLK_8			: return 31 ; break;
	    case SDLK_9			: return 32 ; break;
	    case SDLK_COLON		: return 33 ; break;
	    case SDLK_SEMICOLON	: return 34 ; break;
	    case SDLK_LESS		: return 35 ; break;
	    case SDLK_EQUALS	: return 36 ; break;
	    case SDLK_GREATER	: return 37 ; break;
	    case SDLK_QUESTION	: return 38 ; break;
	    case SDLK_AT		: return 39 ; break;
	    case SDLK_LEFTBRACKET:return 40 ; break;
	    case SDLK_BACKSLASH	: return 41 ; break;
	    case SDLK_RIGHTBRACKET:return 42 ; break;
	    case SDLK_CARET		: return 43 ; break;
	    case SDLK_UNDERSCORE: return 44 ; break;
	    case SDLK_BACKQUOTE	: return 45 ; break;
	    case SDLK_a			: return 46 ; break;
	    case SDLK_b			: return 47 ; break;
	    case SDLK_c			: return 48 ; break;
	    case SDLK_d			: return 49 ; break;
	    case SDLK_e			: return 50 ; break;
	    case SDLK_f			: return 51 ; break;
	    case SDLK_g			: return 52 ; break;
	    case SDLK_h			: return 53 ; break;
	    case SDLK_i			: return 54 ; break;
	    case SDLK_j			: return 55 ; break;
	    case SDLK_k			: return 56 ; break;
	    case SDLK_l			: return 57 ; break;
	    case SDLK_m			: return 58 ; break;
	    case SDLK_n			: return 59 ; break;
	    case SDLK_o			: return 60 ; break;
	    case SDLK_p			: return 61 ; break;
	    case SDLK_q			: return 62 ; break;
	    case SDLK_r			: return 63 ; break;
	    case SDLK_s			: return 64 ; break;
	    case SDLK_t			: return 65 ; break;
	    case SDLK_u			: return 66 ; break;
	    case SDLK_v			: return 67 ; break;
	    case SDLK_w			: return 68 ; break;
	    case SDLK_x			: return 69 ; break;
	    case SDLK_y			: return 70 ; break;
	    case SDLK_z			: return 71 ; break;
	    case SDLK_DELETE	: return 72 ; break;
	    case SDLK_WORLD_0	: return 73 ; break;       
	    case SDLK_WORLD_1	: return 74 ; break;
	    case SDLK_WORLD_2	: return 75 ; break;
	    case SDLK_WORLD_3	: return 76 ; break;
	    case SDLK_WORLD_4	: return 77 ; break;
	    case SDLK_WORLD_5	: return 78 ; break;
	    case SDLK_WORLD_6	: return 79 ; break;
	    case SDLK_WORLD_7	: return 80 ; break;
	    case SDLK_WORLD_8	: return 81 ; break;
	    case SDLK_WORLD_9	: return 82 ; break;
	    case SDLK_WORLD_10	: return 83 ; break;
	    case SDLK_WORLD_11	: return 84 ; break;
	    case SDLK_WORLD_12	: return 85 ; break;
	    case SDLK_WORLD_13	: return 86 ; break;
	    case SDLK_WORLD_14	: return 87 ; break;
	    case SDLK_WORLD_15	: return 88 ; break;
	    case SDLK_WORLD_16	: return 89 ; break;
	    case SDLK_WORLD_17	: return 90 ; break;
	    case SDLK_WORLD_18	: return 91 ; break;
	    case SDLK_WORLD_19	: return 92 ; break;
	    case SDLK_WORLD_20	: return 93 ; break;
	    case SDLK_WORLD_21	: return 94 ; break;
	    case SDLK_WORLD_22	: return 95 ; break;
	    case SDLK_WORLD_23	: return 96 ; break;
	    case SDLK_WORLD_24	: return 97 ; break;
	    case SDLK_WORLD_25	: return 98 ; break;
	    case SDLK_WORLD_26	: return 99 ; break;
	    case SDLK_WORLD_27	: return 100; break;
	    case SDLK_WORLD_28	: return 101; break;
	    case SDLK_WORLD_29	: return 102; break;
	    case SDLK_WORLD_30	: return 103; break;
	    case SDLK_WORLD_31	: return 104; break;
	    case SDLK_WORLD_32	: return 105; break;
	    case SDLK_WORLD_33	: return 106; break;
	    case SDLK_WORLD_34	: return 107; break;
	    case SDLK_WORLD_35	: return 108; break;
	    case SDLK_WORLD_36	: return 109; break;
	    case SDLK_WORLD_37	: return 110; break;
	    case SDLK_WORLD_38	: return 111; break;
	    case SDLK_WORLD_39	: return 112; break;
	    case SDLK_WORLD_40	: return 113; break;
	    case SDLK_WORLD_41	: return 114; break;
	    case SDLK_WORLD_42	: return 115; break;
	    case SDLK_WORLD_43	: return 116; break;
	    case SDLK_WORLD_44	: return 117; break;
	    case SDLK_WORLD_45	: return 118; break;
	    case SDLK_WORLD_46	: return 119; break;
	    case SDLK_WORLD_47	: return 120; break;
	    case SDLK_WORLD_48	: return 121; break;
	    case SDLK_WORLD_49	: return 122; break;
	    case SDLK_WORLD_50	: return 123; break;
	    case SDLK_WORLD_51	: return 124; break;
	    case SDLK_WORLD_52	: return 125; break;
	    case SDLK_WORLD_53	: return 126; break;
	    case SDLK_WORLD_54	: return 127; break;
	    case SDLK_WORLD_55	: return 128; break;
	    case SDLK_WORLD_56	: return 129; break;
	    case SDLK_WORLD_57	: return 130; break;
	    case SDLK_WORLD_58	: return 131; break;
	    case SDLK_WORLD_59	: return 132; break;
	    case SDLK_WORLD_60	: return 133; break;
	    case SDLK_WORLD_61	: return 134; break;
	    case SDLK_WORLD_62	: return 135; break;
	    case SDLK_WORLD_63	: return 136; break;
	    case SDLK_WORLD_64	: return 137; break;
	    case SDLK_WORLD_65	: return 138; break;
	    case SDLK_WORLD_66	: return 139; break;
	    case SDLK_WORLD_67	: return 140; break;
	    case SDLK_WORLD_68	: return 141; break;
	    case SDLK_WORLD_69	: return 142; break;
	    case SDLK_WORLD_70	: return 143; break;
	    case SDLK_WORLD_71	: return 144; break;
	    case SDLK_WORLD_72	: return 145; break;
	    case SDLK_WORLD_73	: return 146; break;
	    case SDLK_WORLD_74	: return 147; break;
	    case SDLK_WORLD_75	: return 148; break;
	    case SDLK_WORLD_76	: return 149; break;
	    case SDLK_WORLD_77	: return 150; break;
	    case SDLK_WORLD_78	: return 151; break;
	    case SDLK_WORLD_79	: return 152; break;
	    case SDLK_WORLD_80	: return 153; break;
	    case SDLK_WORLD_81	: return 154; break;
	    case SDLK_WORLD_82	: return 155; break;
	    case SDLK_WORLD_83	: return 156; break;
	    case SDLK_WORLD_84	: return 157; break;
	    case SDLK_WORLD_85	: return 158; break;
	    case SDLK_WORLD_86	: return 159; break;
	    case SDLK_WORLD_87	: return 160; break;
	    case SDLK_WORLD_88	: return 161; break;
	    case SDLK_WORLD_89	: return 162; break;
	    case SDLK_WORLD_90	: return 163; break;
	    case SDLK_WORLD_91	: return 164; break;
	    case SDLK_WORLD_92	: return 165; break;
	    case SDLK_WORLD_93	: return 166; break;
	    case SDLK_WORLD_94	: return 167; break;
	    case SDLK_WORLD_95	: return 168; break;       
	    case SDLK_KP0		: return 169; break;
	    case SDLK_KP1		: return 170; break;
	    case SDLK_KP2		: return 171; break;
	    case SDLK_KP3		: return 172; break;
	    case SDLK_KP4		: return 173; break;
	    case SDLK_KP5		: return 174; break;
	    case SDLK_KP6		: return 175; break;
	    case SDLK_KP7		: return 176; break;
	    case SDLK_KP8		: return 177; break;
	    case SDLK_KP9		: return 178; break;
	    case SDLK_KP_PERIOD	: return 179; break;
	    case SDLK_KP_DIVIDE	: return 180; break;
	    case SDLK_KP_MULTIPLY:return 181; break;
	    case SDLK_KP_MINUS	: return 182; break;
	    case SDLK_KP_PLUS	: return 183; break;
	    case SDLK_KP_ENTER	: return 184; break;
	    case SDLK_KP_EQUALS	: return 185; break;
	    case SDLK_UP		: return 186; break;
	    case SDLK_DOWN		: return 187; break;
	    case SDLK_RIGHT		: return 188; break;
	    case SDLK_LEFT		: return 189; break;
	    case SDLK_INSERT	: return 190; break;
	    case SDLK_HOME		: return 191; break;
	    case SDLK_END		: return 192; break;
	    case SDLK_PAGEUP	: return 193; break;
	    case SDLK_PAGEDOWN	: return 194; break;
	    case SDLK_F1		: return 195; break;
	    case SDLK_F2		: return 196; break;
	    case SDLK_F3		: return 197; break;
	    case SDLK_F4		: return 198; break;
	    case SDLK_F5		: return 199; break;
	    case SDLK_F6		: return 200; break;
	    case SDLK_F7		: return 201; break;
	    case SDLK_F8		: return 202; break;
	    case SDLK_F9		: return 203; break;
	    case SDLK_F10		: return 204; break;
	    case SDLK_F11		: return 205; break;
	    case SDLK_F12		: return 206; break;
	    case SDLK_F13		: return 207; break;
	    case SDLK_F14		: return 208; break;
	    case SDLK_F15		: return 209; break;
	    case SDLK_NUMLOCK	: return 210; break;
	    case SDLK_CAPSLOCK	: return 211; break;
	    case SDLK_SCROLLOCK	: return 212; break;
	    case SDLK_RSHIFT	: return 213; break;
	    case SDLK_LSHIFT	: return 214; break;
	    case SDLK_RCTRL		: return 215; break;
	    case SDLK_LCTRL		: return 216; break;
	    case SDLK_RALT		: return 217; break;
	    case SDLK_LALT		: return 218; break;
	    case SDLK_RMETA		: return 219; break;
	    case SDLK_LMETA		: return 220; break;
	    case SDLK_LSUPER	: return 221; break;       
	    case SDLK_RSUPER	: return 222; break;       
	    case SDLK_MODE		: return 223; break;       
	    case SDLK_COMPOSE	: return 224; break;       
	    case SDLK_HELP		: return 225; break;
	    case SDLK_PRINT		: return 226; break;
	    case SDLK_SYSREQ	: return 227; break;
	    case SDLK_BREAK		: return 228; break;
	    case SDLK_MENU		: return 229; break;
	    case SDLK_POWER		: return 230; break;   
	    case SDLK_EURO		: return 231; break;   
	    case SDLK_UNDO		: return 232; break;   
	    case SDLK_LAST      : return 233; break;
        default             : return 0;
    };
}

int mod_to_ml_enum(SDLMod mod)
{
	switch(mod)
	{
		case KMOD_LSHIFT : return 1; break;
		case KMOD_RSHIFT : return 2; break;
		case KMOD_LCTRL  : return 3; break;
		case KMOD_RCTRL  : return 4; break;
		case KMOD_LALT   : return 5; break;
		case KMOD_RALT   : return 6; break;
		case KMOD_LMETA  : return 7; break;
		case KMOD_RMETA  : return 8; break;
		case KMOD_NUM    : return 9; break;
		case KMOD_CAPS   : return 10; break;
		case KMOD_MODE   : return 11; break;
		case KMOD_NONE   : 
		default          : return 0;		   	   
	}
}

value hal_get_app_state(value flag)
{
    CAMLparam1(flag);
    int r = 0;
    int appstate = FN(SDL_GetAppState)();
    switch(Int_val(flag))
    {
        case 0: if (appstate & SDL_APPMOUSEFOCUS) r = 1; break; 
        case 1: if (appstate & SDL_APPINPUTFOCUS) r = 1; break; 
        case 2: if (appstate & SDL_APPACTIVE)     r = 1; break; 
        default: break;
    }
   CAMLreturn(Val_bool(r)); 
}

value hal_enable_key_repeat(value delay, value interval)
{
	CAMLparam2(delay, interval);
	if (FN(SDL_EnableKeyRepeat)(Int_val(delay), Int_val(interval)) == -1)
		caml_failwith(FN(SDL_GetError)());
	else CAMLreturn(Val_unit);
}

value hal_get_mod_state(value u)
{
	CAMLparam1(u);
    CAMLlocal2(clr, cons);
    SDLMod mod = FN(SDL_GetModState)(); 
    clr = Val_emptylist;
    #define PUSH(i) \
        cons = caml_alloc(2, 0); \
        Store_field( cons, 0, Val_int(i) );   \
        Store_field( cons, 1, clr );  \
        clr = cons
    if( mod & KMOD_NONE   ){ PUSH(0); } 
    if( mod & KMOD_LSHIFT ){ PUSH(1); } 
    if( mod & KMOD_RSHIFT ){ PUSH(2); } 
    if( mod & KMOD_LCTRL  ){ PUSH(3); } 
    if( mod & KMOD_RCTRL  ){ PUSH(4); } 
    if( mod & KMOD_LALT   ){ PUSH(5); } 
    if( mod & KMOD_RALT   ){ PUSH(6); } 
    if( mod & KMOD_LMETA  ){ PUSH(7); } 
    if( mod & KMOD_RMETA  ){ PUSH(8); } 
    if( mod & KMOD_NUM    ){ PUSH(9); } 
    if( mod & KMOD_CAPS   ){ PUSH(10);} 
    if( mod & KMOD_MODE   ){ PUSH(11);} 
    #undef PUSH
    CAMLreturn(clr);
}


value hal_pump_events(value u)
{
	CAMLparam1(u);
	FN(SDL_PumpEvents)();
	CAMLreturn(Val_unit);
}

value sdl_to_ml_event(SDL_Event event)
{
    CAMLparam0 ();
    CAMLlocal2(ml_event, to_return);
    
    switch (event.type) 
    {
		case SDL_ACTIVEEVENT: 
		{
			ml_event=alloc(2, 0);
			Store_field(ml_event, 0, Val_int(event.active.gain));
			if (event.active.state & SDL_APPACTIVE) 
			    Store_field(ml_event, 1, Val_int(2));
			else if (event.active.state & SDL_APPINPUTFOCUS)
			    Store_field(ml_event, 1, Val_int(1));
			else
			    Store_field(ml_event, 1, Val_int(0));
			to_return=alloc(1,0);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_KEYDOWN:
		case SDL_KEYUP:
		{
			ml_event=alloc(5,0);
			Store_field(ml_event, 0, Val_int(event.key.state));
			Store_field(ml_event, 1, Val_int(event.key.keysym.scancode));
			Store_field(ml_event, 2, Val_int(key_to_ml_enum(event.key.keysym.sym)));
			Store_field(ml_event, 3, Val_int(mod_to_ml_enum(event.key.keysym.mod))); 
			Store_field(ml_event, 4, Val_int(event.key.keysym.unicode));
			to_return=alloc(1, 1);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_MOUSEMOTION:
		{
			ml_event=alloc(5,0);
			switch(event.motion.state)
			{
				case 0: Store_field(ml_event, 0, Val_int(0));break;
				case 1: Store_field(ml_event, 0, Val_int(1));break;
				default: Store_field(ml_event, 0, Val_int(2));break;
			}
			Store_field(ml_event, 1, Val_int(event.motion.x));
			Store_field(ml_event, 2, Val_int(event.motion.y));
			Store_field(ml_event, 3, Val_int(event.motion.xrel));
			Store_field(ml_event, 4, Val_int(event.motion.yrel));
			to_return=alloc(1,2);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
		{
			ml_event=alloc(4,0);
			Store_field(ml_event, 0, Val_int(event.button.button - 1));
			Store_field(ml_event, 1, Val_int(event.button.state));
			Store_field(ml_event, 2, Val_int(event.button.x));
			Store_field(ml_event, 3, Val_int(event.button.y));
			to_return=alloc(1,3);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_JOYAXISMOTION:
		{
			ml_event=alloc(3,0);
			Store_field(ml_event, 0, Val_int(event.jaxis.which));
			Store_field(ml_event, 1, Val_int(event.jaxis.axis));
			Store_field(ml_event, 2, Val_int(event.jaxis.value));
			to_return=alloc(1,4);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_JOYBALLMOTION:
		{
			ml_event=alloc(4,0);
			Store_field(ml_event, 0, Val_int(event.jball.which));
			Store_field(ml_event, 1, Val_int(event.jball.ball));
			Store_field(ml_event, 2, Val_int(event.jball.xrel));
			Store_field(ml_event, 3, Val_int(event.jball.yrel));
			to_return=alloc(1,5);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_JOYHATMOTION:
		{
			ml_event=alloc(3,0);
			Store_field(ml_event, 0, Val_int(event.jhat.which));
			Store_field(ml_event, 1, Val_int(event.jhat.hat));
			Store_field(ml_event, 2, Val_int(event.jhat.value));
			to_return=alloc(1,6);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_JOYBUTTONUP:
		case SDL_JOYBUTTONDOWN:
		{
			ml_event=alloc(3,0);
			Store_field(ml_event, 0, Val_int(event.jbutton.which));
			Store_field(ml_event, 1, Val_int(event.jbutton.button));
			Store_field(ml_event, 2, Val_int(event.jbutton.state));
			to_return=alloc(1,7);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_VIDEORESIZE:
		{
			ml_event=alloc(2,0);
			Store_field(ml_event, 0, Val_int(event.resize.w));
			Store_field(ml_event, 1, Val_int(event.resize.h));
			to_return=alloc(1,8);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_VIDEOEXPOSE:
		{
			CAMLreturn(Val_int(1));
		}
		case SDL_QUIT:
		{
			CAMLreturn(Val_int(2));
		}
		case SDL_USEREVENT:
		{
			ml_event=alloc(3,0);
			Store_field(ml_event, 0, Val_int(event.user.code));
			Store_field(ml_event, 1, (value)(event.user.data1));
			Store_field(ml_event, 2, (value)(event.user.data2));
			to_return=alloc(1,9);
			Store_field(to_return, 0, ml_event);
			CAMLreturn(to_return);
		}
		case SDL_SYSWMEVENT:
		{
			to_return=alloc(1,10);
			Store_field(to_return, 0, (value)(event.syswm.msg));
			CAMLreturn(to_return);
		}
		case SDL_NOEVENT:
		default:
		{
			CAMLreturn(Val_int(0));
		}
    }
}

value hal_poll_event(value unit)
{
	CAMLparam1(unit);
	SDL_Event event;
	FN(SDL_PollEvent)(&event);
	CAMLreturn(sdl_to_ml_event(event));
}

value hal_wait_event(value unit)
{
	CAMLparam1(unit);
	SDL_Event event;
	FN(SDL_PollEvent)(&event);
	CAMLreturn(sdl_to_ml_event(event));
}

value hal_push_event(value pevent)
{
    CAMLparam1(pevent);
    SDL_UserEvent event;
    event.type = SDL_USEREVENT;
    event.code = Int_val(Field(pevent,0));
    event.data1 = (void *)Field(pevent,1);
    event.data2 = (void *)Field(pevent,2);
    if(-1 == FN(SDL_PushEvent)(&event))
    {
        caml_failwith(FN(SDL_GetError)());
    }
    CAMLreturn(Val_unit);
}


/************************* End Events *****************************************/


/****************************** Mouse *****************************************/

value hal_warp_mouse (value x, value y)
{
    CAMLparam2(x,y);
    FN(SDL_WarpMouse)(Int_val(x), Int_val(y));
    CAMLreturn(Val_unit);
}

value hal_show_cursor(value b)
{
    CAMLparam1(b);
    FN(SDL_ShowCursor)(Int_val(b)? 1 : 0);
    CAMLreturn(Val_unit);
}

/****************************** End Mouse**************************************/


/****************************** Time ******************************************/

value hal_delay(value ms)
{
    CAMLparam1(ms);
    FN(SDL_Delay)(Int_val(ms));
    CAMLreturn(Val_unit);
}

value hal_get_ticks(value u)
{
    CAMLparam1(u);
    CAMLreturn(FN(SDL_GetTicks)());
}

/****************************** End  Time *************************************/


/************************** Video *********************************************/


/************************** End video *****************************************/


/************************** Window ********************************************/

value hal_set_video_mode (value width__0, value height__1, value bpp__2) {
	CAMLparam3(width__0, height__1, bpp__2);
	int width = Int_val(width__0);
	int height = Int_val(height__1);
	int bpp = Int_val(bpp__2);
	if (FN(SDL_SetVideoMode)(width, height, bpp, SDL_OPENGL)==NULL)
	{
		caml_failwith(FN(SDL_GetError)());
	}
	CAMLreturn(Val_unit);
}

value hal_set_caption(value title, value icon)
{
	 CAMLparam2(title, icon);
	 FN(SDL_WM_SetCaption)( String_val(title), String_val(icon) );
	 CAMLreturn (Val_unit);
}

value hal_get_caption(value u)
{
	 CAMLparam1(u);
	 CAMLlocal1 (result);
	 char *title, *icon;
	 FN(SDL_WM_GetCaption)( &title, &icon );
     result = caml_alloc(2, 0);
	 Store_field (result, 0, copy_string(title));
	 Store_field (result, 1, copy_string(icon));
	 CAMLreturn (result);  
}

value hal_iconify_window(value u)
{
	CAMLparam1(u);
	FN(SDL_WM_IconifyWindow)();
	CAMLreturn(Val_unit);	
}

value hal_toggle_fullscreen(value u)
{
	CAMLparam1(u);
    SDL_Surface *s = FN(SDL_GetVideoSurface)();
	FN(SDL_WM_ToggleFullScreen)(s);
	CAMLreturn(Val_unit);	
}


value hal_set_grab_input(value b)
{
	CAMLparam1(b);
	int vb = Int_val(b);
	FN(SDL_WM_GrabInput)(vb? SDL_GRAB_ON : SDL_GRAB_OFF);
	CAMLreturn(Val_unit);	
}

/************************ End Window ******************************************/



/*******************************************************************************
                        OPENGL FUNCTIONS
*******************************************************************************/

value glAccum (value op__0, value op_val__1) {
	CAMLparam2(op__0, op_val__1);
	int op = Int_val(op__0);
	double op_val = Double_val(op_val__1);
	FN(glAccum)(op, op_val);
	CAMLreturn(Val_unit);
}

value glAlphaFunc (value func__0, value ref__1) {
	CAMLparam2(func__0, ref__1);
	int func = Int_val(func__0);
	double ref = Double_val(ref__1);
	FN(glAlphaFunc)(func, ref);
	CAMLreturn(Val_unit);
}

value glAreTexturesResident (value textures__0) {
	CAMLparam1(textures__0);
	CAMLlocal1(residences_1);
	int n = MIN(1025, Wosize_val(textures__0));
	static unsigned int textures[1024];
	static unsigned int residences[1024];
	int i, r = FN(glAreTexturesResident)( n, textures, residences);
	residences_1 = caml_alloc( n+1, 0);
	Store_field(residences_1, 0, Val_bool(r));
	for( i = 1; i<n+1; i++ )
	{
		Store_field(residences_1, i, Val_bool(r || residences[i-1]));
	}
	CAMLreturn(residences_1);
}

value glArrayElement (value i__0) {
	CAMLparam1(i__0);
	int i = Int_val(i__0);
	FN(glArrayElement)(i);
	CAMLreturn(Val_unit);
}

value glBegin (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glBegin)(mode);
	CAMLreturn(Val_unit);
}

value glBindTexture (value target__0, value texture__1) {
	CAMLparam2(target__0, texture__1);
	int target = Int_val(target__0);
	int texture = Int_val(texture__1);
	FN(glBindTexture)(target, texture);
	CAMLreturn(Val_unit);
}

value glBitmap (value width__0, value height__1, value xorig__2, value yorig__3, value xmove__4, value ymove__5, value bitmap__6) {
	CAMLparam5(width__0, height__1, xorig__2, yorig__3, xmove__4);
	CAMLxparam2(ymove__5, bitmap__6);
	int width = Int_val(width__0);
	int height = Int_val(height__1);
	double xorig = Double_val(xorig__2);
	double yorig = Double_val(yorig__3);
	double xmove = Double_val(xmove__4);
	double ymove = Double_val(ymove__5);
	unsigned char * bitmap = Data_bigarray_val(bitmap__6);
	FN(glBitmap)(width, height, xorig, yorig, xmove, ymove, bitmap);
	CAMLreturn(Val_unit);
}

value glBitmap_byte(value *argv, int argc)
{
	return glBitmap(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
}

value glBlendFunc (value sfactor__0, value dfactor__1) {
	CAMLparam2(sfactor__0, dfactor__1);
	int sfactor = Int_val(sfactor__0);
	int dfactor = Int_val(dfactor__1);
	FN(glBlendFunc)(sfactor, dfactor);
	CAMLreturn(Val_unit);
}

value glCallList (value list__0) {
	CAMLparam1(list__0);
	int list = Int_val(list__0);
	FN(glCallList)(list);
	CAMLreturn(Val_unit);
}

value glCallLists (value lists__2) {
	CAMLparam1(lists__2);
	int n = MIN(1024, Wosize_val(lists__2));
	int i, lists[1024];
	for(i=0; i<n; i++)
	{
		lists[i] = Int_val(Field(lists__2, i));
	}
	FN(glCallLists)(n, GL_UNSIGNED_INT, lists);
	CAMLreturn(Val_unit);
}

value glClear (value mask__0) {
	CAMLparam1(mask__0);
	int mask = Int_val(mask__0);
	FN(glClear)(mask);
	CAMLreturn(Val_unit);
}

value glClearAccum (value red__0, value green__1, value blue__2, value alpha__3) {
	CAMLparam4(red__0, green__1, blue__2, alpha__3);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	double alpha = Double_val(alpha__3);
	FN(glClearAccum)(red, green, blue, alpha);
	CAMLreturn(Val_unit);
}

value glClearColor (value red__0, value green__1, value blue__2, value alpha__3) {
	CAMLparam4(red__0, green__1, blue__2, alpha__3);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	double alpha = Double_val(alpha__3);
	FN(glClearColor)(red, green, blue, alpha);
	CAMLreturn(Val_unit);
}

value glClearDepth (value depth__0) {
	CAMLparam1(depth__0);
	double depth = Double_val(depth__0);
	FN(glClearDepth)(depth);
	CAMLreturn(Val_unit);
}

value glClearIndex (value c__0) {
	CAMLparam1(c__0);
	double c = Double_val(c__0);
	FN(glClearIndex)(c);
	CAMLreturn(Val_unit);
}

value glClearStencil (value s__0) {
	CAMLparam1(s__0);
	int s = Int_val(s__0);
	FN(glClearStencil)(s);
	CAMLreturn(Val_unit);
}

value glClipPlane (value plane__0, value equation__1) {
	CAMLparam2(plane__0, equation__1);
	int plane = Int_val(plane__0);
	double* equation = (double *)equation__1;
	if(4 > Wosize_val(equation__1))
		caml_failwith("glClipPlane: plane equation array must contain at least 4 floats");
	FN(glClipPlane)(plane, equation);
	CAMLreturn(Val_unit);
}

value glColor3d (value red__0, value green__1, value blue__2) {
	CAMLparam3(red__0, green__1, blue__2);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	FN(glColor3d)(red, green, blue);
	CAMLreturn(Val_unit);
}

value glColor4d (value red__0, value green__1, value blue__2, value alpha__3) {
	CAMLparam4(red__0, green__1, blue__2, alpha__3);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	double alpha = Double_val(alpha__3);
	FN(glColor4d)(red, green, blue, alpha);
	CAMLreturn(Val_unit);
}

value glColorMask (value red__0, value green__1, value blue__2, value alpha__3) {
	CAMLparam4(red__0, green__1, blue__2, alpha__3);
	char red = Bool_val(red__0);
	char green = Bool_val(green__1);
	char blue = Bool_val(blue__2);
	char alpha = Bool_val(alpha__3);
	FN(glColorMask)(red, green, blue, alpha);
	CAMLreturn(Val_unit);
}

value glColorMaterial (value face__0, value mode__1) {
	CAMLparam2(face__0, mode__1);
	int face = Int_val(face__0);
	int mode = Int_val(mode__1);
	FN(glColorMaterial)(face, mode);
	CAMLreturn(Val_unit);
}

value glColorPointer (value pointer__3) {
	CAMLparam1(pointer__3);
	double * pointer = (double *)(pointer__3);
	FN(glColorPointer)(Wosize_val(pointer__3), GL_DOUBLE, 0, pointer);
	CAMLreturn(Val_unit);
}

value glCopyPixels (value x__0, value y__1, value width__2, value height__3, value typ__4) {
	CAMLparam5(x__0, y__1, width__2, height__3, typ__4);
	int x = Int_val(x__0);
	int y = Int_val(y__1);
	int width = Int_val(width__2);
	int height = Int_val(height__3);
	int typ = Int_val(typ__4);
	FN(glCopyPixels)(x, y, width, height, typ);
	CAMLreturn(Val_unit);
}

value glCopyTexImage1D (value target__0, value level__1, value internalFormat__2, value x__3, value y__4, value width__5, value border__6) {
	CAMLparam5(target__0, level__1, internalFormat__2, x__3, y__4);
	CAMLxparam2(width__5, border__6);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalFormat = Int_val(internalFormat__2);
	int x = Int_val(x__3);
	int y = Int_val(y__4);
	int width = Int_val(width__5);
	int border = Int_val(border__6);
	FN(glCopyTexImage1D)(target, level, internalFormat, x, y, width, border);
	CAMLreturn(Val_unit);
}


value glCopyTexImage1D_byte(value *argv, int argc)
{
	return glCopyTexImage1D(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
}


value glCopyTexImage2D (value target__0, value level__1, value internalFormat__2, value x__3, value y__4, value width__5, value height__6, value border__7) {
	CAMLparam5(target__0, level__1, internalFormat__2, x__3, y__4);
	CAMLxparam3(width__5, height__6, border__7);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalFormat = Int_val(internalFormat__2);
	int x = Int_val(x__3);
	int y = Int_val(y__4);
	int width = Int_val(width__5);
	int height = Int_val(height__6);
	int border = Int_val(border__7);
	FN(glCopyTexImage2D)(target, level, internalFormat, x, y, width, height, border);
	CAMLreturn(Val_unit);
}

value glCopyTexSubImage1D (value target__0, value level__1, value xoffset__2, value x__3, value y__4, value width__5) {
	CAMLparam5(target__0, level__1, xoffset__2, x__3, y__4);
	CAMLxparam1(width__5);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int x = Int_val(x__3);
	int y = Int_val(y__4);
	int width = Int_val(width__5);
	FN(glCopyTexSubImage1D)(target, level, xoffset, x, y, width);
	CAMLreturn(Val_unit);
}

value glCopyTexSubImage2D (value target__0, value level__1, value xoffset__2, value yoffset__3, value x__4, value y__5, value width__6, value height__7) {
	CAMLparam5(target__0, level__1, xoffset__2, yoffset__3, x__4);
	CAMLxparam3(y__5, width__6, height__7);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int x = Int_val(x__4);
	int y = Int_val(y__5);
	int width = Int_val(width__6);
	int height = Int_val(height__7);
	FN(glCopyTexSubImage2D)(target, level, xoffset, yoffset, x, y, width, height);
	CAMLreturn(Val_unit);
}

value glCullFace (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glCullFace)(mode);
	CAMLreturn(Val_unit);
}

value glDeleteLists (value list__0, value range__1) {
	CAMLparam2(list__0, range__1);
	int list = Int_val(list__0);
	int range = Int_val(range__1);
	FN(glDeleteLists)(list, range);
	CAMLreturn(Val_unit);
}

value glDeleteTextures (value textures__1) {
	CAMLparam1(textures__1);
	int n = MIN(1024, Wosize_val(textures__1));
	int i, textures[1024];
	for(i=0; i<n; i++)
	{
		textures[i] = Int_val(Field(textures__1, i));
	}	
	FN(glDeleteTextures)(n, textures);
	CAMLreturn(Val_unit);
}

value glDepthFunc (value func__0) {
	CAMLparam1(func__0);
	int func = Int_val(func__0);
	FN(glDepthFunc)(func);
	CAMLreturn(Val_unit);
}

value glDepthMask (value flag__0) {
	CAMLparam1(flag__0);
	char flag = Bool_val(flag__0);
	FN(glDepthMask)(flag);
	CAMLreturn(Val_unit);
}

value glDepthRange (value zNear__0, value zFar__1) {
	CAMLparam2(zNear__0, zFar__1);
	double zNear = Double_val(zNear__0);
	double zFar = Double_val(zFar__1);
	FN(glDepthRange)(zNear, zFar);
	CAMLreturn(Val_unit);
}

value glDisable (value cap__0) {
	CAMLparam1(cap__0);
	int cap = Int_val(cap__0);
	FN(glDisable)(cap);
	CAMLreturn(Val_unit);
}

value glDisableClientState (value array__0) {
	CAMLparam1(array__0);
	int array = Int_val(array__0);
	FN(glDisableClientState)(array);
	CAMLreturn(Val_unit);
}

value glDrawArrays (value mode__0, value first__1, value count__2) {
	CAMLparam3(mode__0, first__1, count__2);
	int mode = Int_val(mode__0);
	int first = Int_val(first__1);
	int count = Int_val(count__2);
	FN(glDrawArrays)(mode, first, count);
	CAMLreturn(Val_unit);
}

value glDrawBuffer (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glDrawBuffer)(mode);
	CAMLreturn(Val_unit);
}

value glDrawElements (value mode__0,  value indices__3) {
	CAMLparam2(mode__0, indices__3);
	int mode = Int_val(mode__0);
	int n = MIN(1024, Wosize_val(indices__3));
	int i, indices[1024];
	for(i=0; i<n; i++)
	{
		indices[i] = Int_val(Field(indices__3, i));
	}
	FN(glDrawElements)(mode, n, GL_INT, indices);
	CAMLreturn(Val_unit);
}

value glDrawPixels (value width__0, value height__1, value format__2, value typ__3, value pixels__4) {
	CAMLparam5(width__0, height__1, format__2, typ__3, pixels__4);
	int width = Int_val(width__0);
	int height = Int_val(height__1);
	int format = Int_val(format__2);
	int typ = Int_val(typ__3);
	unsigned char * pixels = Data_bigarray_val(pixels__4);
	FN(glDrawPixels)(width, height, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glEdgeFlag (value flag__0) {
	CAMLparam1(flag__0);
	char flag = Bool_val(flag__0);
	FN(glEdgeFlag)(flag);
	CAMLreturn(Val_unit);
}

value glEnable (value cap__0) {
	CAMLparam1(cap__0);
	int cap = Int_val(cap__0);
	FN(glEnable)(cap);
	CAMLreturn(Val_unit);
}

value glEnableClientState (value array__0) {
	CAMLparam1(array__0);
	int array = Int_val(array__0);
	FN(glEnableClientState)(array);
	CAMLreturn(Val_unit);
}

value glEnd (value unit__0) {
	CAMLparam1(unit__0);
	FN(glEnd)();
	CAMLreturn(Val_unit);
}

value glEndList (value unit__0) {
	CAMLparam1(unit__0);
	FN(glEndList)();
	CAMLreturn(Val_unit);
}

value glEvalCoord1d (value u__0) {
	CAMLparam1(u__0);
	double u = Double_val(u__0);
	FN(glEvalCoord1d)(u);
	CAMLreturn(Val_unit);
}

value glEvalCoord2d (value u__0, value v__1) {
	CAMLparam2(u__0, v__1);
	double u = Double_val(u__0);
	double v = Double_val(v__1);
	FN(glEvalCoord2d)(u, v);
	CAMLreturn(Val_unit);
}

value glEvalMesh1 (value mode__0, value i1__1, value i2__2) {
	CAMLparam3(mode__0, i1__1, i2__2);
	int mode = Int_val(mode__0);
	int i1 = Int_val(i1__1);
	int i2 = Int_val(i2__2);
	FN(glEvalMesh1)(mode, i1, i2);
	CAMLreturn(Val_unit);
}

value glEvalMesh2 (value mode__0, value i1__1, value i2__2, value j1__3, value j2__4) {
	CAMLparam5(mode__0, i1__1, i2__2, j1__3, j2__4);
	int mode = Int_val(mode__0);
	int i1 = Int_val(i1__1);
	int i2 = Int_val(i2__2);
	int j1 = Int_val(j1__3);
	int j2 = Int_val(j2__4);
	FN(glEvalMesh2)(mode, i1, i2, j1, j2);
	CAMLreturn(Val_unit);
}

value glEvalPoint1 (value i__0) {
	CAMLparam1(i__0);
	int i = Int_val(i__0);
	FN(glEvalPoint1)(i);
	CAMLreturn(Val_unit);
}

value glEvalPoint2 (value i__0, value j__1) {
	CAMLparam2(i__0, j__1);
	int i = Int_val(i__0);
	int j = Int_val(j__1);
	FN(glEvalPoint2)(i, j);
	CAMLreturn(Val_unit);
}

value glFeedbackBuffer (value size__0, value typ__1) {
	CAMLparam2(size__0, typ__1);
	CAMLlocal1(buffer__2);
	int size = MIN(65536, Int_val(size__0));
	int i, typ = Int_val(typ__1);
	static float buffer[65536];
	FN(glFeedbackBuffer)(size, typ, buffer);
	buffer__2 = caml_alloc(size * Double_wosize, Double_array_tag);
	for(i=0; i<size; i++)
	{
		Store_double_field(buffer__2, i, buffer[i]);
	}
	CAMLreturn(buffer__2);
}

value glFinish (value unit__0) {
	CAMLparam1(unit__0);
	FN(glFinish)();
	CAMLreturn(Val_unit);
}

value glFlush (value unit__0) {
	CAMLparam1(unit__0);
	FN(glFlush)();
	CAMLreturn(Val_unit);
}

value glFogf (value pname__0, value param__1) {
	CAMLparam2(pname__0, param__1);
	int pname = Int_val(pname__0);
	double param = Double_val(param__1);
	FN(glFogf)(pname, param);
	CAMLreturn(Val_unit);
}

value glFrontFace (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glFrontFace)(mode);
	CAMLreturn(Val_unit);
}

value glFrustum (value left__0, value right__1, value bottom__2, value top__3, value zNear__4, value zFar__5) {
	CAMLparam5(left__0, right__1, bottom__2, top__3, zNear__4);
	CAMLxparam1(zFar__5);
	double left = Double_val(left__0);
	double right = Double_val(right__1);
	double bottom = Double_val(bottom__2);
	double top = Double_val(top__3);
	double zNear = Double_val(zNear__4);
	double zFar = Double_val(zFar__5);
	FN(glFrustum)(left, right, bottom, top, zNear, zFar);
	CAMLreturn(Val_unit);
}

value glGenLists (value range__0) {
	CAMLparam1(range__0);
	int range = Int_val(range__0);
	int r = FN(glGenLists)(range);
	CAMLreturn(Val_int(r));
}

value glGenTextures (value n__0) {
	CAMLparam1(n__0);
	CAMLlocal1(textures__1);
	int n = MIN(1024, Int_val(n__0));
	int i, textures[1024]; 
	FN(glGenTextures)(n, textures);
	textures__1 = caml_alloc( n, 0);
	for(i = 0; i<n; i++)
	{
		Store_field(textures__1, i, Val_int(textures[i]));
	}
	CAMLreturn(textures__1);
}

value glGetBooleanv (value pname__0) {
	CAMLparam1(pname__0);
	int params, pname = Int_val(pname__0);
	FN(glGetBooleanv)(pname, &params);
	CAMLreturn(Val_bool(params));
}

value glGetClipPlane (value plane__0) {
	CAMLparam1(plane__0);
	CAMLlocal1(equation__1);
	int i, plane = Int_val(plane__0);
	double equation[4];
	FN(glGetClipPlane)(plane, equation);
	equation__1 = caml_alloc(4 * Double_wosize, Double_array_tag);
	for(i=0; i<4; i++)
	{
		Store_double_field(equation__1, i, equation[i]);
	}
	CAMLreturn(equation__1);
}

value glGetDoublev (value pname__0) {
	CAMLparam1(pname__0);
	int pname = Int_val(pname__0);
	double params ;
	FN(glGetDoublev)(pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetError (value unit__0) {
	CAMLparam1(unit__0);
	int r = FN(glGetError)();
	CAMLreturn(Val_int(r));
}

value glGetFloatv (value pname__0) {
	CAMLparam1(pname__0);
	int pname = Int_val(pname__0);
	float params ;
	FN(glGetFloatv)(pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetIntegerv (value pname__0) {
	CAMLparam1(pname__0);
	int params, pname = Int_val(pname__0);
	FN(glGetIntegerv)(pname, &params);
	CAMLreturn(Val_int(params));
}

value glGetLightfv (value light__0, value pname__1) {
	CAMLparam2(light__0, pname__1);
	int light = Int_val(light__0);
	int pname = Int_val(pname__1);
	float params;
	FN(glGetLightfv)(light, pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetMapdv (value target__0, value query__1) {
	CAMLparam2(target__0, query__1);
	int target = Int_val(target__0);
	int query = Int_val(query__1);
	double v;
	FN(glGetMapdv)(target, query, &v);
	CAMLreturn(caml_copy_double(v));
}

value glGetMaterialfv (value face__0, value pname__1) {
	CAMLparam2(face__0, pname__1);
	int face = Int_val(face__0);
	int pname = Int_val(pname__1);
	float params;
	FN(glGetMaterialfv)(face, pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetPixelMapfv (value map__0) {
	CAMLparam1(map__0);
	int map = Int_val(map__0);
	float values;
	FN(glGetPixelMapfv)(map, &values);
	CAMLreturn(caml_copy_double(values));
}

value glGetPointerv (value pname__0) {
	CAMLparam1(pname__0);
	int pname = Int_val(pname__0);
	void *params;
	FN(glGetPointerv)(pname, &params);
	CAMLreturn((value)params);
}

value glGetString (value name__0) {
	CAMLparam1(name__0);
	int name = Int_val(name__0);
	char* r = FN(glGetString)(name);
	CAMLreturn(caml_copy_string(r));
}

value glGetTexEnvfv (value target__0, value pname__1) {
	CAMLparam2(target__0, pname__1);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	float params;
	FN(glGetTexEnvfv)(target, pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetTexEnviv (value target__0, value pname__1) {
	CAMLparam2(target__0, pname__1);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	int params;
	FN(glGetTexEnviv)(target, pname, &params);
	CAMLreturn(Val_int(params));
}

value glGetTexGendv (value coord__0, value pname__1) {
	CAMLparam2(coord__0, pname__1);
	CAMLlocal1(r);
	int coord = Int_val(coord__0);
	int i, pname = Int_val(pname__1);
	double params[4];
	FN(glGetTexGendv)(coord, pname, params);
	r = caml_alloc(4 * Double_wosize, Double_array_tag);
	for(i=0; i<4; i++)
	{
		Store_double_field(r, i, params[i]);
	}
	CAMLreturn(r);
}

value glGetTexImage (value target__0, value level__1, value format__2, value typ__3, value pixels__4) {
	CAMLparam5(target__0, level__1, format__2, typ__3, pixels__4);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int format = Int_val(format__2);
	int typ = Int_val(typ__3);
	unsigned char * pixels = Data_bigarray_val(pixels__4);
	FN(glGetTexImage)(target, level, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glGetTexLevelParameterfv (value target__0, value level__1, value pname__2) {
	CAMLparam3(target__0, level__1, pname__2);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int pname = Int_val(pname__2);
	float params;
	FN(glGetTexLevelParameterfv)(target, level, pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glGetTexParameterfv (value target__0, value pname__1) {
	CAMLparam2(target__0, pname__1);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	float params;
	FN(glGetTexParameterfv)(target, pname, &params);
	CAMLreturn(caml_copy_double(params));
}

value glHint (value target__0, value mode__1) {
	CAMLparam2(target__0, mode__1);
	int target = Int_val(target__0);
	int mode = Int_val(mode__1);
	FN(glHint)(target, mode);
	CAMLreturn(Val_unit);
}

value glIndexMask (value mask__0) {
	CAMLparam1(mask__0);
	int mask = Int_val(mask__0);
	FN(glIndexMask)(mask);
	CAMLreturn(Val_unit);
}

value glIndexPointer (value typ__0, value stride__1, value pointer__2) {
	CAMLparam3(typ__0, stride__1, pointer__2);
	int typ = Int_val(typ__0);
	int stride = Int_val(stride__1);
	unsigned char * pointer = Data_bigarray_val(pointer__2);
	FN(glIndexPointer)(typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glIndexd (value c__0) {
	CAMLparam1(c__0);
	double c = Double_val(c__0);
	FN(glIndexd)(c);
	CAMLreturn(Val_unit);
}

value glInitNames (value unit__0) {
	CAMLparam1(unit__0);
	FN(glInitNames)();
	CAMLreturn(Val_unit);
}

value glInterleavedArrays (value format__0, value stride__1, value pointer__2) {
	CAMLparam3(format__0, stride__1, pointer__2);
	int format = Int_val(format__0);
	int stride = Int_val(stride__1);
	unsigned char * pointer = Data_bigarray_val(pointer__2);
	FN(glInterleavedArrays)(format, stride, pointer);
	CAMLreturn(Val_unit);
}

value glIsEnabled (value cap__0) {
	CAMLparam1(cap__0);
	int cap = Int_val(cap__0);
	int r = FN(glIsEnabled)(cap);
	CAMLreturn(Val_bool(r));
}

value glIsList (value list__0) {
	CAMLparam1(list__0);
	int list = Int_val(list__0);
	int r = FN(glIsList)(list);
	CAMLreturn(Val_bool(r));
}

value glIsTexture (value texture__0) {
	CAMLparam1(texture__0);
	int texture = Int_val(texture__0);
	int r = FN(glIsTexture)(texture);
	CAMLreturn(Val_bool(r));
}

value glLightModelf (value pname__0, value param__1) {
	CAMLparam2(pname__0, param__1);
	int pname = Int_val(pname__0);
	double param = Double_val(param__1);
	FN(glLightModelf)(pname, param);
	CAMLreturn(Val_unit);
}

value glLightf (value light__0, value pname__1, value param__2) {
	CAMLparam3(light__0, pname__1, param__2);
	int light = Int_val(light__0);
	int pname = Int_val(pname__1);
	double param = Double_val(param__2);
	FN(glLightf)(light, pname, param);
	CAMLreturn(Val_unit);
}

value glLineStipple (value factor__0, value pattern__1) {
	CAMLparam2(factor__0, pattern__1);
	int factor = Int_val(factor__0);
	int pattern = Int_val(pattern__1);
	FN(glLineStipple)(factor, pattern);
	CAMLreturn(Val_unit);
}

value glLineWidth (value width__0) {
	CAMLparam1(width__0);
	double width = Double_val(width__0);
	FN(glLineWidth)(width);
	CAMLreturn(Val_unit);
}

value glListBase (value base__0) {
	CAMLparam1(base__0);
	int base = Int_val(base__0);
	FN(glListBase)(base);
	CAMLreturn(Val_unit);
}

value glLoadIdentity (value unit__0) {
	CAMLparam1(unit__0);
	FN(glLoadIdentity)();
	CAMLreturn(Val_unit);
}

value glLoadMatrixd (value m__0) {
	CAMLparam1(m__0);
	double *m = (double *)m__0;
	FN(glLoadMatrixd)(m);
	CAMLreturn(Val_unit);
}

value glLoadName (value name__0) {
	CAMLparam1(name__0);
	int name = Int_val(name__0);
	FN(glLoadName)(name);
	CAMLreturn(Val_unit);
}

value glLogicOp (value opcode__0) {
	CAMLparam1(opcode__0);
	int opcode = Int_val(opcode__0);
	FN(glLogicOp)(opcode);
	CAMLreturn(Val_unit);
}

value glMap1d (value target__0, value u1__1, value u2__2, value stride__3, value order__4, value points__5) {
	CAMLparam5(target__0, u1__1, u2__2, stride__3, order__4);
	CAMLxparam1(points__5);
	int target = Int_val(target__0);
	double u1 = Double_val(u1__1);
	double u2 = Double_val(u2__2);
	int stride = Int_val(stride__3);
	int order = Int_val(order__4);
	double *points = (double *)points__5;
	FN(glMap1d)(target, u1, u2, stride, order, points);
	CAMLreturn(Val_unit);
}

value glMap2d (value target__0, value u1__1, value u2__2, value ustride__3, value uorder__4, value v1__5, value v2__6, value vstride__7, value vorder__8, value points__9) {
	CAMLparam5(target__0, u1__1, u2__2, ustride__3, uorder__4);
	CAMLxparam5(v1__5, v2__6, vstride__7, vorder__8, points__9);
	int target = Int_val(target__0);
	double u1 = Double_val(u1__1);
	double u2 = Double_val(u2__2);
	int ustride = Int_val(ustride__3);
	int uorder = Int_val(uorder__4);
	double v1 = Double_val(v1__5);
	double v2 = Double_val(v2__6);
	int vstride = Int_val(vstride__7);
	int vorder = Int_val(vorder__8);
	double *points = (double *)points__9;
	FN(glMap2d)(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, points);
	CAMLreturn(Val_unit);
}

value glMapGrid1d (value un__0, value u1__1, value u2__2) {
	CAMLparam3(un__0, u1__1, u2__2);
	int un = Int_val(un__0);
	double u1 = Double_val(u1__1);
	double u2 = Double_val(u2__2);
	FN(glMapGrid1d)(un, u1, u2);
	CAMLreturn(Val_unit);
}

value glMapGrid2d (value un__0, value u1__1, value u2__2, value vn__3, value v1__4, value v2__5) {
	CAMLparam5(un__0, u1__1, u2__2, vn__3, v1__4);
	CAMLxparam1(v2__5);
	int un = Int_val(un__0);
	double u1 = Double_val(u1__1);
	double u2 = Double_val(u2__2);
	int vn = Int_val(vn__3);
	double v1 = Double_val(v1__4);
	double v2 = Double_val(v2__5);
	FN(glMapGrid2d)(un, u1, u2, vn, v1, v2);
	CAMLreturn(Val_unit);
}

value glMaterialf (value face__0, value pname__1, value param__2) {
	CAMLparam3(face__0, pname__1, param__2);
	int face = Int_val(face__0);
	int pname = Int_val(pname__1);
	double param = Double_val(param__2);
	FN(glMaterialf)(face, pname, param);
	CAMLreturn(Val_unit);
}

value glMatrixMode (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glMatrixMode)(mode);
	CAMLreturn(Val_unit);
}

value glMultMatrixd (value m__0) {
	CAMLparam1(m__0);
	double *m = (double *)m__0;
	FN(glMultMatrixd)(m);
	CAMLreturn(Val_unit);
}

value glNewList (value list__0, value mode__1) {
	CAMLparam2(list__0, mode__1);
	int list = Int_val(list__0);
	int mode = Int_val(mode__1);
	FN(glNewList)(list, mode);
	CAMLreturn(Val_unit);
}

value glNormal3d (value nx__0, value ny__1, value nz__2) {
	CAMLparam3(nx__0, ny__1, nz__2);
	double nx = Double_val(nx__0);
	double ny = Double_val(ny__1);
	double nz = Double_val(nz__2);
	FN(glNormal3d)(nx, ny, nz);
	CAMLreturn(Val_unit);
}

value glNormalPointer (value typ__0, value stride__1, value pointer__2) {
	CAMLparam3(typ__0, stride__1, pointer__2);
	int typ = Int_val(typ__0);
	int stride = Int_val(stride__1);
	unsigned char * pointer = Data_bigarray_val(pointer__2);
	FN(glNormalPointer)(typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glOrtho (value left__0, value right__1, value bottom__2, value top__3, value zNear__4, value zFar__5) {
	CAMLparam5(left__0, right__1, bottom__2, top__3, zNear__4);
	CAMLxparam1(zFar__5);
	double left = Double_val(left__0);
	double right = Double_val(right__1);
	double bottom = Double_val(bottom__2);
	double top = Double_val(top__3);
	double zNear = Double_val(zNear__4);
	double zFar = Double_val(zFar__5);
	FN(glOrtho)(left, right, bottom, top, zNear, zFar);
	CAMLreturn(Val_unit);
}

value glPassThrough (value token__0) {
	CAMLparam1(token__0);
	double token = Double_val(token__0);
	FN(glPassThrough)(token);
	CAMLreturn(Val_unit);
}

value glPixelMapfv (value map__0, value values__2) {
	CAMLparam2(map__0, values__2);
	int map = Int_val(map__0);
	int i, mapsize = MIN(1024, Wosize_val(values__2));
	float values[1024];
	double *v = (double *)values__2;
	for(i=0; i<mapsize; i++)
	{
		values[i] = v[i];
	}
	FN(glPixelMapfv)(map, mapsize, values);
	CAMLreturn(Val_unit);
}

value glPixelStoref (value pname__0, value param__1) {
	CAMLparam2(pname__0, param__1);
	int pname = Int_val(pname__0);
	double param = Double_val(param__1);
	FN(glPixelStoref)(pname, param);
	CAMLreturn(Val_unit);
}

value glPixelTransferf (value pname__0, value param__1) {
	CAMLparam2(pname__0, param__1);
	int pname = Int_val(pname__0);
	double param = Double_val(param__1);
	FN(glPixelTransferf)(pname, param);
	CAMLreturn(Val_unit);
}

value glPixelZoom (value xfactor__0, value yfactor__1) {
	CAMLparam2(xfactor__0, yfactor__1);
	double xfactor = Double_val(xfactor__0);
	double yfactor = Double_val(yfactor__1);
	FN(glPixelZoom)(xfactor, yfactor);
	CAMLreturn(Val_unit);
}

value glPointSize (value size__0) {
	CAMLparam1(size__0);
	double size = Double_val(size__0);
	FN(glPointSize)(size);
	CAMLreturn(Val_unit);
}

value glPolygonMode (value face__0, value mode__1) {
	CAMLparam2(face__0, mode__1);
	int face = Int_val(face__0);
	int mode = Int_val(mode__1);
	FN(glPolygonMode)(face, mode);
	CAMLreturn(Val_unit);
}

value glPolygonOffset (value factor__0, value units__1) {
	CAMLparam2(factor__0, units__1);
	double factor = Double_val(factor__0);
	double units = Double_val(units__1);
	FN(glPolygonOffset)(factor, units);
	CAMLreturn(Val_unit);
}

value glPolygonStipple (value mask__0) {
	CAMLparam1(mask__0);
	unsigned char * mask = Data_bigarray_val(mask__0);
	FN(glPolygonStipple)(mask);
	CAMLreturn(Val_unit);
}

value glPopAttrib (value unit__0) {
	CAMLparam1(unit__0);
	FN(glPopAttrib)();
	CAMLreturn(Val_unit);
}

value glPopClientAttrib (value unit__0) {
	CAMLparam1(unit__0);
	FN(glPopClientAttrib)();
	CAMLreturn(Val_unit);
}

value glPopMatrix (value unit__0) {
	CAMLparam1(unit__0);
	FN(glPopMatrix)();
	CAMLreturn(Val_unit);
}

value glPopName (value unit__0) {
	CAMLparam1(unit__0);
	FN(glPopName)();
	CAMLreturn(Val_unit);
}

value glPrioritizeTextures (value textures__1) {
	CAMLparam1(textures__1);
	CAMLlocal1(r);
	int i, n = MIN(1024, Wosize_val(textures__1));
	static int textures[1024];
	static float priorities[1024];
	FN(glPrioritizeTextures)(n, textures, priorities);
	r = caml_alloc(n, 0);
	for(i=0; i<n; i++)
	{
		Store_field(r, 0, caml_copy_double(priorities[i]));
	}
	CAMLreturn(r);
}

value glPushAttrib (value mask__0) {
	CAMLparam1(mask__0);
	int mask = Int_val(mask__0);
	FN(glPushAttrib)(mask);
	CAMLreturn(Val_unit);
}

value glPushClientAttrib (value mask__0) {
	CAMLparam1(mask__0);
	int mask = Int_val(mask__0);
	FN(glPushClientAttrib)(mask);
	CAMLreturn(Val_unit);
}

value glPushMatrix (value unit__0) {
	CAMLparam1(unit__0);
	FN(glPushMatrix)();
	CAMLreturn(Val_unit);
}

value glPushName (value name__0) {
	CAMLparam1(name__0);
	int name = Int_val(name__0);
	FN(glPushName)(name);
	CAMLreturn(Val_unit);
}

value glRasterPos2d (value x__0, value y__1) {
	CAMLparam2(x__0, y__1);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	FN(glRasterPos2d)(x, y);
	CAMLreturn(Val_unit);
}

value glRasterPos3d (value x__0, value y__1, value z__2) {
	CAMLparam3(x__0, y__1, z__2);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	FN(glRasterPos3d)(x, y, z);
	CAMLreturn(Val_unit);
}

value glRasterPos4d (value x__0, value y__1, value z__2, value w__3) {
	CAMLparam4(x__0, y__1, z__2, w__3);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	double w = Double_val(w__3);
	FN(glRasterPos4d)(x, y, z, w);
	CAMLreturn(Val_unit);
}

value glReadBuffer (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glReadBuffer)(mode);
	CAMLreturn(Val_unit);
}

value glReadPixels (value x__0, value y__1, value width__2, value height__3, value format__4, value typ__5, value pixels__6) {
	CAMLparam5(x__0, y__1, width__2, height__3, format__4);
	CAMLxparam2(typ__5, pixels__6);
	int x = Int_val(x__0);
	int y = Int_val(y__1);
	int width = Int_val(width__2);
	int height = Int_val(height__3);
	int format = Int_val(format__4);
	int typ = Int_val(typ__5);
	unsigned char * pixels = Data_bigarray_val(pixels__6);
	FN(glReadPixels)(x, y, width, height, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glRectd (value x1__0, value y1__1, value x2__2, value y2__3) {
	CAMLparam4(x1__0, y1__1, x2__2, y2__3);
	double x1 = Double_val(x1__0);
	double y1 = Double_val(y1__1);
	double x2 = Double_val(x2__2);
	double y2 = Double_val(y2__3);
	FN(glRectd)(x1, y1, x2, y2);
	CAMLreturn(Val_unit);
}

value glRenderMode (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	int r = FN(glRenderMode)(mode);
	CAMLreturn(Val_int(r));
}

value glRotated (value angle__0, value x__1, value y__2, value z__3) {
	CAMLparam4(angle__0, x__1, y__2, z__3);
	double angle = Double_val(angle__0);
	double x = Double_val(x__1);
	double y = Double_val(y__2);
	double z = Double_val(z__3);
	FN(glRotated)(angle, x, y, z);
	CAMLreturn(Val_unit);
}

value glScaled (value x__0, value y__1, value z__2) {
	CAMLparam3(x__0, y__1, z__2);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	FN(glScaled)(x, y, z);
	CAMLreturn(Val_unit);
}

value glScissor (value x__0, value y__1, value width__2, value height__3) {
	CAMLparam4(x__0, y__1, width__2, height__3);
	int x = Int_val(x__0);
	int y = Int_val(y__1);
	int width = Int_val(width__2);
	int height = Int_val(height__3);
	FN(glScissor)(x, y, width, height);
	CAMLreturn(Val_unit);
}

value glSelectBuffer (value u) {
	CAMLparam1(u);
	static int buffer[1024];
	FN(glSelectBuffer)(1024, buffer);
	CAMLreturn(Val_unit);
}

value glShadeModel (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glShadeModel)(mode);
	CAMLreturn(Val_unit);
}

value glStencilFunc (value func__0, value ref__1, value mask__2) {
	CAMLparam3(func__0, ref__1, mask__2);
	int func = Int_val(func__0);
	int ref = Int_val(ref__1);
	int mask = Int_val(mask__2);
	FN(glStencilFunc)(func, ref, mask);
	CAMLreturn(Val_unit);
}

value glStencilMask (value mask__0) {
	CAMLparam1(mask__0);
	int mask = Int_val(mask__0);
	FN(glStencilMask)(mask);
	CAMLreturn(Val_unit);
}

value glStencilOp (value fail__0, value zfail__1, value zpass__2) {
	CAMLparam3(fail__0, zfail__1, zpass__2);
	int fail = Int_val(fail__0);
	int zfail = Int_val(zfail__1);
	int zpass = Int_val(zpass__2);
	FN(glStencilOp)(fail, zfail, zpass);
	CAMLreturn(Val_unit);
}

value glTexCoord1d (value s__0) {
	CAMLparam1(s__0);
	double s = Double_val(s__0);
	FN(glTexCoord1d)(s);
	CAMLreturn(Val_unit);
}

value glTexCoord2d (value s__0, value t__1) {
	CAMLparam2(s__0, t__1);
	double s = Double_val(s__0);
	double t = Double_val(t__1);
	FN(glTexCoord2d)(s, t);
	CAMLreturn(Val_unit);
}

value glTexCoord3d (value s__0, value t__1, value r__2) {
	CAMLparam3(s__0, t__1, r__2);
	double s = Double_val(s__0);
	double t = Double_val(t__1);
	double r = Double_val(r__2);
	FN(glTexCoord3d)(s, t, r);
	CAMLreturn(Val_unit);
}

value glTexCoord4d (value s__0, value t__1, value r__2, value q__3) {
	CAMLparam4(s__0, t__1, r__2, q__3);
	double s = Double_val(s__0);
	double t = Double_val(t__1);
	double r = Double_val(r__2);
	double q = Double_val(q__3);
	FN(glTexCoord4d)(s, t, r, q);
	CAMLreturn(Val_unit);
}

value glTexCoordPointer (value size__0, value typ__1, value stride__2, value pointer__3) {
	CAMLparam4(size__0, typ__1, stride__2, pointer__3);
	int size = Int_val(size__0);
	int typ = Int_val(typ__1);
	int stride = Int_val(stride__2);
	unsigned char * pointer = Data_bigarray_val(pointer__3);
	FN(glTexCoordPointer)(size, typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glTexEnvf (value target__0, value pname__1, value param__2) {
	CAMLparam3(target__0, pname__1, param__2);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	double param = Double_val(param__2);
	FN(glTexEnvf)(target, pname, param);
	CAMLreturn(Val_unit);
}

value glTexGend (value coord__0, value pname__1, value param__2) {
	CAMLparam3(coord__0, pname__1, param__2);
	int coord = Int_val(coord__0);
	int pname = Int_val(pname__1);
	double param = Double_val(param__2);
	FN(glTexGend)(coord, pname, param);
	CAMLreturn(Val_unit);
}

value glTexImage1D (value target__0, value level__1, value internalformat__2, value width__3, value border__4, value format__5, value typ__6, value pixels__7) {
	CAMLparam5(target__0, level__1, internalformat__2, width__3, border__4);
	CAMLxparam3(format__5, typ__6, pixels__7);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalformat = Int_val(internalformat__2);
	int width = Int_val(width__3);
	int border = Int_val(border__4);
	int format = Int_val(format__5);
	int typ = Int_val(typ__6);
	unsigned char * pixels = Data_bigarray_val(pixels__7);
	FN(glTexImage1D)(target, level, internalformat, width, border, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glTexImage2D (value target__0, value level__1, value internalformat__2, value width__3, value height__4, value border__5, value format__6, value typ__7, value pixels__8) {
	CAMLparam5(target__0, level__1, internalformat__2, width__3, height__4);
	CAMLxparam4(border__5, format__6, typ__7, pixels__8);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalformat = Int_val(internalformat__2);
	int width = Int_val(width__3);
	int height = Int_val(height__4);
	int border = Int_val(border__5);
	int format = Int_val(format__6);
	int typ = Int_val(typ__7);
	unsigned char * pixels = Data_bigarray_val(pixels__8);
	FN(glTexImage2D)(target, level, internalformat, width, height, border, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glTexParameterf (value target__0, value pname__1, value param__2) {
	CAMLparam3(target__0, pname__1, param__2);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	double param = Double_val(param__2);
	FN(glTexParameterf)(target, pname, param);
	CAMLreturn(Val_unit);
}

value glTexSubImage1D (value target__0, value level__1, value xoffset__2, value width__3, value format__4, value typ__5, value pixels__6) {
	CAMLparam5(target__0, level__1, xoffset__2, width__3, format__4);
	CAMLxparam2(typ__5, pixels__6);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int width = Int_val(width__3);
	int format = Int_val(format__4);
	int typ = Int_val(typ__5);
	unsigned char * pixels = Data_bigarray_val(pixels__6);
	FN(glTexSubImage1D)(target, level, xoffset, width, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glTexSubImage2D (value target__0, value level__1, value xoffset__2, value yoffset__3, value width__4, value height__5, value format__6, value typ__7, value pixels__8) {
	CAMLparam5(target__0, level__1, xoffset__2, yoffset__3, width__4);
	CAMLxparam4(height__5, format__6, typ__7, pixels__8);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int width = Int_val(width__4);
	int height = Int_val(height__5);
	int format = Int_val(format__6);
	int typ = Int_val(typ__7);
	unsigned char * pixels = Data_bigarray_val(pixels__8);
	FN(glTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glTranslated (value x__0, value y__1, value z__2) {
	CAMLparam3(x__0, y__1, z__2);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	FN(glTranslated)(x, y, z);
	CAMLreturn(Val_unit);
}

value glVertex2d (value x__0, value y__1) {
	CAMLparam2(x__0, y__1);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	FN(glVertex2d)(x, y);
	CAMLreturn(Val_unit);
}

value glVertex3d (value x__0, value y__1, value z__2) {
	CAMLparam3(x__0, y__1, z__2);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	FN(glVertex3d)(x, y, z);
	CAMLreturn(Val_unit);
}

value glVertex4d (value x__0, value y__1, value z__2, value w__3) {
	CAMLparam4(x__0, y__1, z__2, w__3);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	double w = Double_val(w__3);
	FN(glVertex4d)(x, y, z, w);
	CAMLreturn(Val_unit);
}

value glVertexPointer (value size__0, value typ__1, value stride__2, value pointer__3) {
	CAMLparam4(size__0, typ__1, stride__2, pointer__3);
	int size = Int_val(size__0);
	int typ = Int_val(typ__1);
	int stride = Int_val(stride__2);
	unsigned char * pointer = Data_bigarray_val(pointer__3);
	FN(glVertexPointer)(size, typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glViewport (value x__0, value y__1, value width__2, value height__3) {
	CAMLparam4(x__0, y__1, width__2, height__3);
	int x = Int_val(x__0);
	int y = Int_val(y__1);
	int width = Int_val(width__2);
	int height = Int_val(height__3);
	FN(glViewport)(x, y, width, height);
	CAMLreturn(Val_unit);
}

/*
 *
 *

value glDrawRangeElements (value mode__0, value start__1, value stop__2, value count__3, value typ__4, value indices__5) {
	CAMLparam6(mode__0, start__1, stop__2, count__3, typ__4, indices__5);
	int mode = Int_val(mode__0);
	int start = Int_val(start__1);
	int stop = Int_val(stop__2);
	int count = Int_val(count__3);
	int typ = Int_val(typ__4);
	unsigned char * indices = Data_bigarray_val(indices__5);
	FN(glDrawRangeElements)(mode, start, stop, count, typ, indices);
	CAMLreturn(Val_unit);
}

value glTexImage3D (value target__0, value level__1, value internalFormat__2, value width__3, value height__4, value depth__5, value border__6, value format__7, value typ__8, value pixels__9) {
	CAMLparam10(target__0, level__1, internalFormat__2, width__3, height__4, depth__5, border__6, format__7, typ__8, pixels__9);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalFormat = Int_val(internalFormat__2);
	int width = Int_val(width__3);
	int height = Int_val(height__4);
	int depth = Int_val(depth__5);
	int border = Int_val(border__6);
	int format = Int_val(format__7);
	int typ = Int_val(typ__8);
	unsigned char * pixels = Data_bigarray_val(pixels__9);
	FN(glTexImage3D)(target, level, internalFormat, width, height, depth, border, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glTexSubImage3D (value target__0, value level__1, value xoffset__2, value yoffset__3, value zoffset__4, value width__5, value height__6, value depth__7, value format__8, value typ__9, value pixels__10) {
	CAMLparam11(target__0, level__1, xoffset__2, yoffset__3, zoffset__4, width__5, height__6, depth__7, format__8, typ__9, pixels__10);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int zoffset = Int_val(zoffset__4);
	int width = Int_val(width__5);
	int height = Int_val(height__6);
	int depth = Int_val(depth__7);
	int format = Int_val(format__8);
	int typ = Int_val(typ__9);
	unsigned char * pixels = Data_bigarray_val(pixels__10);
	FN(glTexSubImage3D)(target, level, xoffset, yoffset, zoffset, width, height, depth, format, typ, pixels);
	CAMLreturn(Val_unit);
}

value glCopyTexSubImage3D (value target__0, value level__1, value xoffset__2, value yoffset__3, value zoffset__4, value x__5, value y__6, value width__7, value height__8) {
	CAMLparam9(target__0, level__1, xoffset__2, yoffset__3, zoffset__4, x__5, y__6, width__7, height__8);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int zoffset = Int_val(zoffset__4);
	int x = Int_val(x__5);
	int y = Int_val(y__6);
	int width = Int_val(width__7);
	int height = Int_val(height__8);
	FN(glCopyTexSubImage3D)(target, level, xoffset, yoffset, zoffset, x, y, width, height);
	CAMLreturn(Val_unit);
}

value glActiveTexture (value texture__0) {
	CAMLparam1(texture__0);
	int texture = Int_val(texture__0);
	FN(glActiveTexture)(texture);
	CAMLreturn(Val_unit);
}

value glClientActiveTexture (value texture__0) {
	CAMLparam1(texture__0);
	int texture = Int_val(texture__0);
	FN(glClientActiveTexture)(texture);
	CAMLreturn(Val_unit);
}

value glCompressedTexImage1D (value target__0, value level__1, value internalformat__2, value width__3, value border__4, value imageSize__5, value data__6) {
	CAMLparam7(target__0, level__1, internalformat__2, width__3, border__4, imageSize__5, data__6);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalformat = Int_val(internalformat__2);
	int width = Int_val(width__3);
	int border = Int_val(border__4);
	int imageSize = Int_val(imageSize__5);
	unsigned char * data = Data_bigarray_val(data__6);
	FN(glCompressedTexImage1D)(target, level, internalformat, width, border, imageSize, data);
	CAMLreturn(Val_unit);
}

value glCompressedTexImage2D (value target__0, value level__1, value internalformat__2, value width__3, value height__4, value border__5, value imageSize__6, value data__7) {
	CAMLparam8(target__0, level__1, internalformat__2, width__3, height__4, border__5, imageSize__6, data__7);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalformat = Int_val(internalformat__2);
	int width = Int_val(width__3);
	int height = Int_val(height__4);
	int border = Int_val(border__5);
	int imageSize = Int_val(imageSize__6);
	unsigned char * data = Data_bigarray_val(data__7);
	FN(glCompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data);
	CAMLreturn(Val_unit);
}

value glCompressedTexImage3D (value target__0, value level__1, value internalformat__2, value width__3, value height__4, value depth__5, value border__6, value imageSize__7, value data__8) {
	CAMLparam9(target__0, level__1, internalformat__2, width__3, height__4, depth__5, border__6, imageSize__7, data__8);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int internalformat = Int_val(internalformat__2);
	int width = Int_val(width__3);
	int height = Int_val(height__4);
	int depth = Int_val(depth__5);
	int border = Int_val(border__6);
	int imageSize = Int_val(imageSize__7);
	unsigned char * data = Data_bigarray_val(data__8);
	FN(glCompressedTexImage3D)(target, level, internalformat, width, height, depth, border, imageSize, data);
	CAMLreturn(Val_unit);
}

value glCompressedTexSubImage1D (value target__0, value level__1, value xoffset__2, value width__3, value format__4, value imageSize__5, value data__6) {
	CAMLparam7(target__0, level__1, xoffset__2, width__3, format__4, imageSize__5, data__6);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int width = Int_val(width__3);
	int format = Int_val(format__4);
	int imageSize = Int_val(imageSize__5);
	unsigned char * data = Data_bigarray_val(data__6);
	FN(glCompressedTexSubImage1D)(target, level, xoffset, width, format, imageSize, data);
	CAMLreturn(Val_unit);
}

value glCompressedTexSubImage2D (value target__0, value level__1, value xoffset__2, value yoffset__3, value width__4, value height__5, value format__6, value imageSize__7, value data__8) {
	CAMLparam9(target__0, level__1, xoffset__2, yoffset__3, width__4, height__5, format__6, imageSize__7, data__8);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int width = Int_val(width__4);
	int height = Int_val(height__5);
	int format = Int_val(format__6);
	int imageSize = Int_val(imageSize__7);
	unsigned char * data = Data_bigarray_val(data__8);
	FN(glCompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data);
	CAMLreturn(Val_unit);
}

value glCompressedTexSubImage3D (value target__0, value level__1, value xoffset__2, value yoffset__3, value zoffset__4, value width__5, value height__6, value depth__7, value format__8, value imageSize__9, value data__10) {
	CAMLparam11(target__0, level__1, xoffset__2, yoffset__3, zoffset__4, width__5, height__6, depth__7, format__8, imageSize__9, data__10);
	int target = Int_val(target__0);
	int level = Int_val(level__1);
	int xoffset = Int_val(xoffset__2);
	int yoffset = Int_val(yoffset__3);
	int zoffset = Int_val(zoffset__4);
	int width = Int_val(width__5);
	int height = Int_val(height__6);
	int depth = Int_val(depth__7);
	int format = Int_val(format__8);
	int imageSize = Int_val(imageSize__9);
	unsigned char * data = Data_bigarray_val(data__10);
	FN(glCompressedTexSubImage3D)(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
	CAMLreturn(Val_unit);
}

value glGetCompressedTexImage (value target__0, value lod__1, value img__2) {
	CAMLparam3(target__0, lod__1, img__2);
	int target = Int_val(target__0);
	int lod = Int_val(lod__1);
	unsigned char * img = Data_bigarray_val(img__2);
	FN(glGetCompressedTexImage)(target, lod, img);
	CAMLreturn(Val_unit);
}

value glLoadTransposeMatrixd (value m__0) {
	CAMLparam1(m__0);
	value m = m__0;
	FN(glLoadTransposeMatrixd)(m);
	CAMLreturn(Val_unit);
}

value glMultTransposeMatrixd (value m__0) {
	CAMLparam1(m__0);
	value m = m__0;
	FN(glMultTransposeMatrixd)(m);
	CAMLreturn(Val_unit);
}

value glMultiTexCoord1d (value target__0, value s__1) {
	CAMLparam2(target__0, s__1);
	int target = Int_val(target__0);
	double s = Double_val(s__1);
	FN(glMultiTexCoord1d)(target, s);
	CAMLreturn(Val_unit);
}

value glMultiTexCoord2d (value target__0, value s__1, value t__2) {
	CAMLparam3(target__0, s__1, t__2);
	int target = Int_val(target__0);
	double s = Double_val(s__1);
	double t = Double_val(t__2);
	FN(glMultiTexCoord2d)(target, s, t);
	CAMLreturn(Val_unit);
}

value glMultiTexCoord3d (value target__0, value s__1, value t__2, value r__3) {
	CAMLparam4(target__0, s__1, t__2, r__3);
	int target = Int_val(target__0);
	double s = Double_val(s__1);
	double t = Double_val(t__2);
	double r = Double_val(r__3);
	FN(glMultiTexCoord3d)(target, s, t, r);
	CAMLreturn(Val_unit);
}

value glMultiTexCoord4d (value target__0, value s__1, value t__2, value r__3, value q__4) {
	CAMLparam5(target__0, s__1, t__2, r__3, q__4);
	int target = Int_val(target__0);
	double s = Double_val(s__1);
	double t = Double_val(t__2);
	double r = Double_val(r__3);
	double q = Double_val(q__4);
	FN(glMultiTexCoord4d)(target, s, t, r, q);
	CAMLreturn(Val_unit);
}

value glSampleCoverage (value value__0, value invert__1) {
	CAMLparam2(value__0, invert__1);
	double value = Double_val(value__0);
	char invert = Bool_val(invert__1);
	FN(glSampleCoverage)(value, invert);
	CAMLreturn(Val_unit);
}

value glBlendEquation (value mode__0) {
	CAMLparam1(mode__0);
	int mode = Int_val(mode__0);
	FN(glBlendEquation)(mode);
	CAMLreturn(Val_unit);
}

value glBlendColor (value red__0, value green__1, value blue__2, value alpha__3) {
	CAMLparam4(red__0, green__1, blue__2, alpha__3);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	double alpha = Double_val(alpha__3);
	FN(glBlendColor)(red, green, blue, alpha);
	CAMLreturn(Val_unit);
}

value glFogCoordd (value coord__0) {
	CAMLparam1(coord__0);
	double coord = Double_val(coord__0);
	FN(glFogCoordd)(coord);
	CAMLreturn(Val_unit);
}

value glFogCoordPointer (value typ__0, value stride__1, value pointer__2) {
	CAMLparam3(typ__0, stride__1, pointer__2);
	int typ = Int_val(typ__0);
	int stride = Int_val(stride__1);
	unsigned char * pointer = Data_bigarray_val(pointer__2);
	FN(glFogCoordPointer)(typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glMultiDrawArrays (value mode__0, value first__1, value count__2, value primcount__3) {
	CAMLparam4(mode__0, first__1, count__2, primcount__3);
	int mode = Int_val(mode__0);
	value first = first__1;
	value count = count__2;
	int primcount = Int_val(primcount__3);
	FN(glMultiDrawArrays)(mode, first, count, primcount);
	CAMLreturn(Val_unit);
}

value glMultiDrawElements (value mode__0, value count__1, value typ__2, value indices__3, value primcount__4) {
	CAMLparam5(mode__0, count__1, typ__2, indices__3, primcount__4);
	int mode = Int_val(mode__0);
	value count = count__1;
	int typ = Int_val(typ__2);
	value indices = indices__3;
	int primcount = Int_val(primcount__4);
	FN(glMultiDrawElements)(mode, count, typ, indices, primcount);
	CAMLreturn(Val_unit);
}

value glPointParameterf (value pname__0, value param__1) {
	CAMLparam2(pname__0, param__1);
	int pname = Int_val(pname__0);
	double param = Double_val(param__1);
	FN(glPointParameterf)(pname, param);
	CAMLreturn(Val_unit);
}

value glSecondaryColor3d (value red__0, value green__1, value blue__2) {
	CAMLparam3(red__0, green__1, blue__2);
	double red = Double_val(red__0);
	double green = Double_val(green__1);
	double blue = Double_val(blue__2);
	FN(glSecondaryColor3d)(red, green, blue);
	CAMLreturn(Val_unit);
}

value glSecondaryColorPointer (value size__0, value typ__1, value stride__2, value pointer__3) {
	CAMLparam4(size__0, typ__1, stride__2, pointer__3);
	int size = Int_val(size__0);
	int typ = Int_val(typ__1);
	int stride = Int_val(stride__2);
	unsigned char * pointer = Data_bigarray_val(pointer__3);
	FN(glSecondaryColorPointer)(size, typ, stride, pointer);
	CAMLreturn(Val_unit);
}

value glBlendFuncSeparate (value sfactorRGB__0, value dfactorRGB__1, value sfactorAlpha__2, value dfactorAlpha__3) {
	CAMLparam4(sfactorRGB__0, dfactorRGB__1, sfactorAlpha__2, dfactorAlpha__3);
	int sfactorRGB = Int_val(sfactorRGB__0);
	int dfactorRGB = Int_val(dfactorRGB__1);
	int sfactorAlpha = Int_val(sfactorAlpha__2);
	int dfactorAlpha = Int_val(dfactorAlpha__3);
	FN(glBlendFuncSeparate)(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
	CAMLreturn(Val_unit);
}

value glWindowPos2d (value x__0, value y__1) {
	CAMLparam2(x__0, y__1);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	FN(glWindowPos2d)(x, y);
	CAMLreturn(Val_unit);
}

value glWindowPos3d (value x__0, value y__1, value z__2) {
	CAMLparam3(x__0, y__1, z__2);
	double x = Double_val(x__0);
	double y = Double_val(y__1);
	double z = Double_val(z__2);
	FN(glWindowPos3d)(x, y, z);
	CAMLreturn(Val_unit);
}

value glGenQueries (value n__0, value ids__1) {
	CAMLparam2(n__0, ids__1);
	int n = Int_val(n__0);
	value ids = ids__1;
	FN(glGenQueries)(n, ids);
	CAMLreturn(Val_unit);
}

value glDeleteQueries (value n__0, value ids__1) {
	CAMLparam2(n__0, ids__1);
	int n = Int_val(n__0);
	value ids = ids__1;
	FN(glDeleteQueries)(n, ids);
	CAMLreturn(Val_unit);
}

value glIsQuery (value id__0) {
	CAMLparam1(id__0);
	int id = Int_val(id__0);
	int r = FN(glIsQuery)(id);
	Return(r);
}

value glBeginQuery (value target__0, value id__1) {
	CAMLparam2(target__0, id__1);
	int target = Int_val(target__0);
	int id = Int_val(id__1);
	FN(glBeginQuery)(target, id);
	CAMLreturn(Val_unit);
}

value glEndQuery (value target__0) {
	CAMLparam1(target__0);
	int target = Int_val(target__0);
	FN(glEndQuery)(target);
	CAMLreturn(Val_unit);
}

value glGetQueryiv (value target__0, value pname__1, value params__2) {
	CAMLparam3(target__0, pname__1, params__2);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	value params = params__2;
	FN(glGetQueryiv)(target, pname, params);
	CAMLreturn(Val_unit);
}

value glGetQueryObjectiv (value id__0, value pname__1, value params__2) {
	CAMLparam3(id__0, pname__1, params__2);
	int id = Int_val(id__0);
	int pname = Int_val(pname__1);
	value params = params__2;
	FN(glGetQueryObjectiv)(id, pname, params);
	CAMLreturn(Val_unit);
}

value glBindBuffer (value target__0, value buffer__1) {
	CAMLparam2(target__0, buffer__1);
	int target = Int_val(target__0);
	int buffer = Int_val(buffer__1);
	FN(glBindBuffer)(target, buffer);
	CAMLreturn(Val_unit);
}

value glDeleteBuffers (value n__0, value buffers__1) {
	CAMLparam2(n__0, buffers__1);
	int n = Int_val(n__0);
	value buffers = buffers__1;
	FN(glDeleteBuffers)(n, buffers);
	CAMLreturn(Val_unit);
}

value glGenBuffers (value n__0, value buffers__1) {
	CAMLparam2(n__0, buffers__1);
	int n = Int_val(n__0);
	value buffers = buffers__1;
	FN(glGenBuffers)(n, buffers);
	CAMLreturn(Val_unit);
}

value glIsBuffer (value buffer__0) {
	CAMLparam1(buffer__0);
	int buffer = Int_val(buffer__0);
	int r = FN(glIsBuffer)(buffer);
	Return(r);
}

value glBufferData (value target__0, value size__1, value data__2, value usage__3) {
	CAMLparam4(target__0, size__1, data__2, usage__3);
	int target = Int_val(target__0);
	int size = Int_val(size__1);
	unsigned char * data = Data_bigarray_val(data__2);
	int usage = Int_val(usage__3);
	FN(glBufferData)(target, size, data, usage);
	CAMLreturn(Val_unit);
}

value glBufferSubData (value target__0, value offset__1, value size__2, value data__3) {
	CAMLparam4(target__0, offset__1, size__2, data__3);
	int target = Int_val(target__0);
	int offset = Int_val(offset__1);
	int size = Int_val(size__2);
	unsigned char * data = Data_bigarray_val(data__3);
	FN(glBufferSubData)(target, offset, size, data);
	CAMLreturn(Val_unit);
}

value glGetBufferSubData (value target__0, value offset__1, value size__2, value data__3) {
	CAMLparam4(target__0, offset__1, size__2, data__3);
	int target = Int_val(target__0);
	int offset = Int_val(offset__1);
	int size = Int_val(size__2);
	unsigned char * data = Data_bigarray_val(data__3);
	FN(glGetBufferSubData)(target, offset, size, data);
	CAMLreturn(Val_unit);
}

value glMapBuffer (value target__0, value access__1) {
	CAMLparam2(target__0, access__1);
	int target = Int_val(target__0);
	int access = Int_val(access__1);
	void* r = FN(glMapBuffer)(target, access);
	Return(r);
}

value glUnmapBuffer (value target__0) {
	CAMLparam1(target__0);
	int target = Int_val(target__0);
	int r = FN(glUnmapBuffer)(target);
	Return(r);
}

value glGetBufferParameteriv (value target__0, value pname__1, value params__2) {
	CAMLparam3(target__0, pname__1, params__2);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	value params = params__2;
	FN(glGetBufferParameteriv)(target, pname, params);
	CAMLreturn(Val_unit);
}

value glGetBufferPointerv (value target__0, value pname__1, value params__2) {
	CAMLparam3(target__0, pname__1, params__2);
	int target = Int_val(target__0);
	int pname = Int_val(pname__1);
	value params = params__2;
	FN(glGetBufferPointerv)(target, pname, params);
	CAMLreturn(Val_unit);
}

value glBlendEquationSeparate (value b__0, value b__1) {
	CAMLparam2(b__0, b__1);
	int b = Int_val(b__0);
	int b = Int_val(b__1);
	FN(glBlendEquationSeparate)(b, b);
	CAMLreturn(Val_unit);
}

value glDrawBuffers (value n__0, value bufs__1) {
	CAMLparam2(n__0, bufs__1);
	int n = Int_val(n__0);
	value bufs = bufs__1;
	FN(glDrawBuffers)(n, bufs);
	CAMLreturn(Val_unit);
}

value glStencilOpSeparate (value face__0, value sfail__1, value dpfail__2, value dppass__3) {
	CAMLparam4(face__0, sfail__1, dpfail__2, dppass__3);
	int face = Int_val(face__0);
	int sfail = Int_val(sfail__1);
	int dpfail = Int_val(dpfail__2);
	int dppass = Int_val(dppass__3);
	FN(glStencilOpSeparate)(face, sfail, dpfail, dppass);
	CAMLreturn(Val_unit);
}

value glStencilFuncSeparate (value frontfunc__0, value backfunc__1, value ref__2, value mask__3) {
	CAMLparam4(frontfunc__0, backfunc__1, ref__2, mask__3);
	int frontfunc = Int_val(frontfunc__0);
	int backfunc = Int_val(backfunc__1);
	int ref = Int_val(ref__2);
	int mask = Int_val(mask__3);
	FN(glStencilFuncSeparate)(frontfunc, backfunc, ref, mask);
	CAMLreturn(Val_unit);
}

value glStencilMaskSeparate (value b__0, value a__1) {
	CAMLparam2(b__0, a__1);
	int b = Int_val(b__0);
	int a = Int_val(a__1);
	FN(glStencilMaskSeparate)(b, a);
	CAMLreturn(Val_unit);
}

value glAttachShader (value program__0, value shader__1) {
	CAMLparam2(program__0, shader__1);
	int program = Int_val(program__0);
	int shader = Int_val(shader__1);
	FN(glAttachShader)(program, shader);
	CAMLreturn(Val_unit);
}

value glBindAttribLocation (value program__0, value index__1, value name__2) {
	CAMLparam3(program__0, index__1, name__2);
	int program = Int_val(program__0);
	int index = Int_val(index__1);
	char* name = String_val(name__2);
	FN(glBindAttribLocation)(program, index, name);
	CAMLreturn(Val_unit);
}

value glCompileShader (value shader__0) {
	CAMLparam1(shader__0);
	int shader = Int_val(shader__0);
	FN(glCompileShader)(shader);
	CAMLreturn(Val_unit);
}

value glCreateProgram (value unit__0) {
	CAMLparam1(unit__0);
	int r = FN(glCreateProgram)(void);
	Return(r);
}

value glCreateShader (value typ__0) {
	CAMLparam1(typ__0);
	int typ = Int_val(typ__0);
	int r = FN(glCreateShader)(typ);
	Return(r);
}

value glDeleteProgram (value program__0) {
	CAMLparam1(program__0);
	int program = Int_val(program__0);
	FN(glDeleteProgram)(program);
	CAMLreturn(Val_unit);
}

value glDeleteShader (value shader__0) {
	CAMLparam1(shader__0);
	int shader = Int_val(shader__0);
	FN(glDeleteShader)(shader);
	CAMLreturn(Val_unit);
}

value glDetachShader (value program__0, value shader__1) {
	CAMLparam2(program__0, shader__1);
	int program = Int_val(program__0);
	int shader = Int_val(shader__1);
	FN(glDetachShader)(program, shader);
	CAMLreturn(Val_unit);
}

value glDisableVertexAttribArray (value a__0) {
	CAMLparam1(a__0);
	int a = Int_val(a__0);
	FN(glDisableVertexAttribArray)(a);
	CAMLreturn(Val_unit);
}

value glEnableVertexAttribArray (value a__0) {
	CAMLparam1(a__0);
	int a = Int_val(a__0);
	FN(glEnableVertexAttribArray)(a);
	CAMLreturn(Val_unit);
}

value glGetActiveAttrib (value program__0, value index__1, value maxLength__2, value length__3, value size__4, value typ__5, value name__6) {
	CAMLparam7(program__0, index__1, maxLength__2, length__3, size__4, typ__5, name__6);
	int program = Int_val(program__0);
	int index = Int_val(index__1);
	int maxLength = Int_val(maxLength__2);
	value length = length__3;
	value size = size__4;
	value typ = typ__5;
	char* name = String_val(name__6);
	FN(glGetActiveAttrib)(program, index, maxLength, length, size, typ, name);
	CAMLreturn(Val_unit);
}

value glGetActiveUniform (value program__0, value index__1, value maxLength__2, value length__3, value size__4, value typ__5, value name__6) {
	CAMLparam7(program__0, index__1, maxLength__2, length__3, size__4, typ__5, name__6);
	int program = Int_val(program__0);
	int index = Int_val(index__1);
	int maxLength = Int_val(maxLength__2);
	value length = length__3;
	value size = size__4;
	value typ = typ__5;
	char* name = String_val(name__6);
	FN(glGetActiveUniform)(program, index, maxLength, length, size, typ, name);
	CAMLreturn(Val_unit);
}

value glGetAttachedShaders (value program__0, value maxCount__1, value count__2, value shaders__3) {
	CAMLparam4(program__0, maxCount__1, count__2, shaders__3);
	int program = Int_val(program__0);
	int maxCount = Int_val(maxCount__1);
	value count = count__2;
	value shaders = shaders__3;
	FN(glGetAttachedShaders)(program, maxCount, count, shaders);
	CAMLreturn(Val_unit);
}

value glGetAttribLocation (value program__0, value name__1) {
	CAMLparam2(program__0, name__1);
	int program = Int_val(program__0);
	char* name = String_val(name__1);
	int r = FN(glGetAttribLocation)(program, name);
	Return(r);
}

value glGetProgramiv (value program__0, value pname__1, value param__2) {
	CAMLparam3(program__0, pname__1, param__2);
	int program = Int_val(program__0);
	int pname = Int_val(pname__1);
	value param = param__2;
	FN(glGetProgramiv)(program, pname, param);
	CAMLreturn(Val_unit);
}

value glGetProgramInfoLog (value program__0, value bufSize__1, value length__2, value infoLog__3) {
	CAMLparam4(program__0, bufSize__1, length__2, infoLog__3);
	int program = Int_val(program__0);
	int bufSize = Int_val(bufSize__1);
	value length = length__2;
	char* infoLog = String_val(infoLog__3);
	FN(glGetProgramInfoLog)(program, bufSize, length, infoLog);
	CAMLreturn(Val_unit);
}

value glGetShaderiv (value shader__0, value pname__1, value param__2) {
	CAMLparam3(shader__0, pname__1, param__2);
	int shader = Int_val(shader__0);
	int pname = Int_val(pname__1);
	value param = param__2;
	FN(glGetShaderiv)(shader, pname, param);
	CAMLreturn(Val_unit);
}

value glGetShaderInfoLog (value shader__0, value bufSize__1, value length__2, value infoLog__3) {
	CAMLparam4(shader__0, bufSize__1, length__2, infoLog__3);
	int shader = Int_val(shader__0);
	int bufSize = Int_val(bufSize__1);
	value length = length__2;
	char* infoLog = String_val(infoLog__3);
	FN(glGetShaderInfoLog)(shader, bufSize, length, infoLog);
	CAMLreturn(Val_unit);
}

value glShaderSource (value shader__0, value count__1, value strings__2, value lengths__3) {
	CAMLparam4(shader__0, count__1, strings__2, lengths__3);
	int shader = Int_val(shader__0);
	int count = Int_val(count__1);
	value strings = strings__2;
	value lengths = lengths__3;
	FN(glShaderSource)(shader, count, strings, lengths);
	CAMLreturn(Val_unit);
}

value glGetUniformLocation (value programObj__0, value name__1) {
	CAMLparam2(programObj__0, name__1);
	int programObj = Int_val(programObj__0);
	char* name = String_val(name__1);
	int r = FN(glGetUniformLocation)(programObj, name);
	Return(r);
}

value glGetUniformfv (value program__0, value location__1, value params__2) {
	CAMLparam3(program__0, location__1, params__2);
	int program = Int_val(program__0);
	int location = Int_val(location__1);
	value params = params__2;
	FN(glGetUniformfv)(program, location, params);
	CAMLreturn(Val_unit);
}

value glGetVertexAttribdv (value a__0, value b__1, value a__2) {
	CAMLparam3(a__0, b__1, a__2);
	int a = Int_val(a__0);
	int b = Int_val(b__1);
	value a = a__2;
	FN(glGetVertexAttribdv)(a, b, a);
	CAMLreturn(Val_unit);
}

value glIsProgram (value program__0) {
	CAMLparam1(program__0);
	int program = Int_val(program__0);
	int r = FN(glIsProgram)(program);
	Return(r);
}

value glIsShader (value shader__0) {
	CAMLparam1(shader__0);
	int shader = Int_val(shader__0);
	int r = FN(glIsShader)(shader);
	Return(r);
}

value glLinkProgram (value program__0) {
	CAMLparam1(program__0);
	int program = Int_val(program__0);
	FN(glLinkProgram)(program);
	CAMLreturn(Val_unit);
}

value glGetShaderSource (value obj__0, value maxLength__1, value length__2, value source__3) {
	CAMLparam4(obj__0, maxLength__1, length__2, source__3);
	int obj = Int_val(obj__0);
	int maxLength = Int_val(maxLength__1);
	value length = length__2;
	char* source = String_val(source__3);
	FN(glGetShaderSource)(obj, maxLength, length, source);
	CAMLreturn(Val_unit);
}

value glUseProgram (value program__0) {
	CAMLparam1(program__0);
	int program = Int_val(program__0);
	FN(glUseProgram)(program);
	CAMLreturn(Val_unit);
}

value glUniform1f (value location__0, value v0__1) {
	CAMLparam2(location__0, v0__1);
	int location = Int_val(location__0);
	double v0 = Double_val(v0__1);
	FN(glUniform1f)(location, v0);
	CAMLreturn(Val_unit);
}

value glUniform2f (value location__0, value v0__1, value v1__2) {
	CAMLparam3(location__0, v0__1, v1__2);
	int location = Int_val(location__0);
	double v0 = Double_val(v0__1);
	double v1 = Double_val(v1__2);
	FN(glUniform2f)(location, v0, v1);
	CAMLreturn(Val_unit);
}

value glUniform3f (value location__0, value v0__1, value v1__2, value v2__3) {
	CAMLparam4(location__0, v0__1, v1__2, v2__3);
	int location = Int_val(location__0);
	double v0 = Double_val(v0__1);
	double v1 = Double_val(v1__2);
	double v2 = Double_val(v2__3);
	FN(glUniform3f)(location, v0, v1, v2);
	CAMLreturn(Val_unit);
}

value glUniform4f (value location__0, value v0__1, value v1__2, value v2__3, value v3__4) {
	CAMLparam5(location__0, v0__1, v1__2, v2__3, v3__4);
	int location = Int_val(location__0);
	double v0 = Double_val(v0__1);
	double v1 = Double_val(v1__2);
	double v2 = Double_val(v2__3);
	double v3 = Double_val(v3__4);
	FN(glUniform4f)(location, v0, v1, v2, v3);
	CAMLreturn(Val_unit);
}

value glUniformMatrix2fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix2fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix3fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix3fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix4fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix4fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glValidateProgram (value program__0) {
	CAMLparam1(program__0);
	int program = Int_val(program__0);
	FN(glValidateProgram)(program);
	CAMLreturn(Val_unit);
}

value glVertexAttrib1d (value index__0, value x__1) {
	CAMLparam2(index__0, x__1);
	int index = Int_val(index__0);
	double x = Double_val(x__1);
	FN(glVertexAttrib1d)(index, x);
	CAMLreturn(Val_unit);
}

value glVertexAttrib2d (value index__0, value x__1, value y__2) {
	CAMLparam3(index__0, x__1, y__2);
	int index = Int_val(index__0);
	double x = Double_val(x__1);
	double y = Double_val(y__2);
	FN(glVertexAttrib2d)(index, x, y);
	CAMLreturn(Val_unit);
}

value glVertexAttrib3d (value index__0, value x__1, value y__2, value z__3) {
	CAMLparam4(index__0, x__1, y__2, z__3);
	int index = Int_val(index__0);
	double x = Double_val(x__1);
	double y = Double_val(y__2);
	double z = Double_val(z__3);
	FN(glVertexAttrib3d)(index, x, y, z);
	CAMLreturn(Val_unit);
}

value glVertexAttrib4Nub (value index__0, value x__1, value y__2, value z__3, value w__4) {
	CAMLparam5(index__0, x__1, y__2, z__3, w__4);
	int index = Int_val(index__0);
	int x = Int_val(x__1);
	int y = Int_val(y__2);
	int z = Int_val(z__3);
	int w = Int_val(w__4);
	FN(glVertexAttrib4Nub)(index, x, y, z, w);
	CAMLreturn(Val_unit);
}

value glVertexAttrib4d (value index__0, value x__1, value y__2, value z__3, value w__4) {
	CAMLparam5(index__0, x__1, y__2, z__3, w__4);
	int index = Int_val(index__0);
	double x = Double_val(x__1);
	double y = Double_val(y__2);
	double z = Double_val(z__3);
	double w = Double_val(w__4);
	FN(glVertexAttrib4d)(index, x, y, z, w);
	CAMLreturn(Val_unit);
}

value glVertexAttribPointer (value index__0, value size__1, value typ__2, value normalized__3, value stride__4, value pointer__5) {
	CAMLparam6(index__0, size__1, typ__2, normalized__3, stride__4, pointer__5);
	int index = Int_val(index__0);
	int size = Int_val(size__1);
	int typ = Int_val(typ__2);
	char normalized = Bool_val(normalized__3);
	int stride = Int_val(stride__4);
	unsigned char * pointer = Data_bigarray_val(pointer__5);
	FN(glVertexAttribPointer)(index, size, typ, normalized, stride, pointer);
	CAMLreturn(Val_unit);
}

value glUniformMatrix2x3fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix2x3fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix2x4fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix2x4fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix3x2fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix3x2fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix3x4fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix3x4fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix4x2fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	double= value = value__3;
	FN(glUniformMatrix4x2fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}

value glUniformMatrix4x3fv (value location__0, value count__1, value transpose__2, value value__3) {
	CAMLparam4(location__0, count__1, transpose__2, value__3);
	int location = Int_val(location__0);
	int count = Int_val(count__1);
	char transpose = Bool_val(transpose__2);
	value value = value__3;
	FN(glUniformMatrix4x3fv)(location, count, transpose, value);
	CAMLreturn(Val_unit);
}
*/


